home *** CD-ROM | disk | FTP | other *** search
- /*
- File: SimpleText.c
-
- Contains: SimpleText - a simple document editing application for shipping
- with system software.
-
- Version: SimpleText 1.4 or later
-
- ** Copyright 1993-1996 Apple Computer. All rights reserved.
- **
- ** You may incorporate this sample code into your applications without
- ** restriction, though the sample code has been provided "AS IS" and the
- ** responsibility for its operation is 100% yours. However, what you are
- ** not permitted to do is to redistribute the source as "DSC Sample Code"
- ** after having made changes. If you're going to re-distribute the source,
- ** we require that you make it clear in the source that the code was
- ** descended from Apple Sample Code, but that you've made changes.
-
- */
-
- #include "MacIncludes.h"
-
- #include <ImageCompression.h> // for CustomGetFilePreview
- #include <Threads.h>
-
- #define CompilingMain=1
- #include "SimpleText.h"
- #include "Clipboard.h"
-
- // --------------------------------------------------------------------------------------------------------------
- // INTERNAL TYPES AND TYPEDEFS
- // --------------------------------------------------------------------------------------------------------------
-
-
- // refCon value between SimpleCatchShape and GXInstallQDTranslator
- typedef struct
- {
- gxShape thePage;
- gxRectangle thePageRectangle;
- Boolean doLayout;
- gxJob theJob;
- } CatchRefCon;
-
- // --------------------------------------------------------------------------------------------------------------
- // FORWARD DECLARES
- // --------------------------------------------------------------------------------------------------------------
- OSErr DoActivate(WindowRef pWindow, Boolean activating);
- OSErr DoCommand(WindowRef pWindow, short commandID, long menuResult);
- OSErr DoKeyEvent(WindowRef pWindow, EventRecord * pEvent, Boolean processPageControls);
- Boolean CommandToIDs(short commandID, short * menuID, short *itemID);
- void AdjustMenus(WindowRef pWindow, Boolean editDialogs, Boolean forceTitlesOn);
-
- // --------------------------------------------------------------------------------------------------------------
- // GLOBAL VARIABLES
- // --------------------------------------------------------------------------------------------------------------
- EventRecord gEvent; // currently pending event
- Boolean gAllDone; // true if the application is the in process of terminating
- MachineInfoRec gMachineInfo; // info about abilities and options installed on this machine
- short gApplicationResFile; // resource fork of application
- RgnHandle gCursorRgn; // region to control the cursor apearence
- AGRefNum gAGRefNum = -1; // AppleGuide database which is open
- FSSpec gAGSpec; // where to find our database
- AGCoachRefNum gAGCoachRefNum = -1; // coach handler refNum
- FontMappingHandle gFontMappingList = nil; // list of font mappings
- ThreadID gFontThread; // thread that builds font menu
- ThreadID gAGThread; // thread that looks for AppleGuide database
- ThreadID gStarterThread; // starts our other threads for us
- Boolean gDontYield; // whether our threads should yield
- void* gThreadResults; // scratch space for thread results
-
- // These variables are for the find/replace commands
- Str255 gFindString = "\p", gReplaceString = "\p";
- Boolean gWrapAround = false, gCaseSensitive = false;
-
- // Metrowerks MWCRuntime.lib defines qd for us on PPC, and their
- // __runtime module does under the 68K case. OTOH, neither SC nor
- // MrC give us qd for free, so we need it there. I'm still not
- // certain which way to go for the ThinkC or Symantec PPC case.
- #if !defined(__MWERKS__)
- // QuickDraw globals
- QDGlobals qd;
- #endif
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- static pascal Boolean AlertFilter(DialogRef theDialog, EventRecord *theEvent, short *itemHit)
- {
- if (theEvent->what == activateEvt && (DialogRef) theEvent->message == theDialog)
- {
- SetDialogDefaultItem(theDialog, 1);
- }
-
- if (StdFilterProc(theDialog, theEvent, itemHit))
- return true;
-
- // Pass updates through (Activates are tricky...was mucking with Apple menu & thereby
- // drastically changing how the system handles the menu bar during our alert)
- if (theEvent->what == updateEvt /* || theEvent->what == activateEvt */ )
- {
- HandleEvent(theEvent);
- }
-
- return false;
-
- } // AlertFilter
-
-
- void ConductErrorDialog(OSErr error, short commandID, short alertType)
- {
- long foundError; // The error, converted to a number
- short stringIndex; // Index into the strings
- Str255 errorText; // the error in a string format
-
- // Start with no error so far
- foundError = 0;
-
- // Start with the first string
- stringIndex = 1;
-
- // Loop until we find an error string
- errorText[0] = 0;
-
- do
- {
- // Get the string, and convert it to a number
- GetIndString(errorText, kErrorBaseID + commandID, stringIndex);
- if (errorText[0] == 0)
- break;
- StringToNum(errorText, &foundError);
-
- // If we reach the last string, or we match the error code
- if ((foundError == 0) ||
- (foundError == error))
- {
- // Get the text string for this error
- GetIndString(errorText, kErrorBaseID + commandID, stringIndex+1);
- }
- else
- {
- // Otherwise, make us continue until we get a string
- errorText[0] = 0;
- }
-
- // Advance so we get the next string number
- stringIndex += 2;
-
- } while (errorText[0] == 0); // errorText[0] == 0
-
- if (errorText[0] != 0)
- {
- DialogRef dPtr;
- short hit;
-
- SetCursor(&qd.arrow);
- ParamText(errorText, "\p", "\p", "\p");
-
- #if !GENERATINGPOWERPC
- if (gMachineInfo.theEnvirons.systemVersion < 0x0700)
- {
- short ** hDialog;
-
- hDialog = (short**) GetResource('DLOG', kErrorBaseID + alertType);
- (*hDialog)[4] = dBoxProc;
-
- dPtr = GetNewDialog(kErrorBaseID + alertType, nil, (WindowRef)-1);
-
- do
- {
- ModalDialog(nil, &hit);
- } while (hit != ok);
-
- DisposeDialog(dPtr);
- }
- else
- {
- dPtr = GetNewDialog(kErrorBaseID + alertType, nil, (WindowRef)-1);
-
- SetDialogDefaultItem(dPtr, ok);
-
- BeginMovableModal();
-
- do
- {
- MovableModalDialog(nil, &hit);
- } while (hit != ok);
-
- DisposeDialog(dPtr);
- EndMovableModal();
- }
- #else
- dPtr = GetNewDialog(kErrorBaseID + alertType, nil, (WindowRef)-1);
-
- SetDialogDefaultItem(dPtr, ok);
-
- BeginMovableModal();
-
- do
- {
- MovableModalDialog(nil, &hit);
- } while (hit != ok);
-
- DisposeDialog(dPtr);
- EndMovableModal();
- #endif
- }
-
- } // ConductErrorDialog
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- static void MovableModalMenus(DialogRef dPtr, short *pItem, long menuResult)
- {
- short iCut, iCopy, iClear, iPaste;
- short editMenu;
- short menuItem = menuResult & 0xFFFF;
-
- // find out where edit menus are
- CommandToIDs(cCut, &editMenu, &iCut);
- CommandToIDs(cCopy, &editMenu, &iCopy);
- CommandToIDs(cClear, &editMenu, &iClear);
- CommandToIDs(cPaste, &editMenu, &iPaste);
-
- HiliteMenu(0);
- switch (menuResult >> 16)
- {
- case mApple:
- {
- Str255 tempString;
-
- GetMenuItemText(GetMenuHandle(menuResult>>16), menuItem, tempString);
- OpenDeskAcc(tempString);
- }
- break;
-
- case mEdit:
- {
- short type;
- Handle item;
- Rect box;
- short editField = GetDialogKeyboardFocusItem(dPtr);
-
- // return typed item, if it isn't disabled
- GetDialogItem(dPtr, editField, &type, &item, &box);
- if ((type & itemDisable) == 0)
- *pItem = editField;
-
- if (menuItem == iCut)
- {
- DialogCut(dPtr);
- ZeroScrap();
- TEToScrap();
- }
-
- if (menuItem == iCopy)
- {
- DialogCopy(dPtr);
- ZeroScrap();
- TEToScrap();
- }
-
- if (menuItem == iClear)
- DialogDelete(dPtr);
-
- if (menuItem == iPaste)
- DialogPaste(dPtr);
- }
- break;
- }
-
- } // MovableModalMenus
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- void MovableModalDialog(ModalFilterProcPtr filterProc, short *pItem)
- /*
- Call this as you would ModalDialog, when the dialog is moveable
- modal.
-
- However, first call BeginMovableModal, and afterwards (after
- disposing of dialog) call EndMovableModal.
- */
- {
- GrafPtr curPort;
- DialogRef dPtr = FrontWindow();
-
- *pItem = 0;
- if (dPtr)
- {
- GetPort(&curPort);
- SetPort(dPtr);
-
- do
- {
- WaitNextEvent(mDownMask + mUpMask + keyDownMask + keyUpMask + autoKeyMask + updateMask + activMask + osMask,
- &gEvent, 0, nil);
-
- // call the filter proc
- if ( (filterProc) && ((*filterProc) (dPtr, &gEvent, pItem)) )
- break;
-
- // call the basic filtering
- if (StdFilterProc(dPtr, &gEvent, pItem))
- break;
-
- // handle keyboard
- if ((gEvent.what == keyDown) && (gEvent.modifiers & cmdKey))
- {
- MovableModalMenus(dPtr, pItem, MenuKey(gEvent.message & charCodeMask));
- break;
- }
-
- // handle clicks and drags
- if (gEvent.what == mouseDown)
- {
- WindowRef whichWindow;
- short part = FindWindow(gEvent.where, &whichWindow);
-
- // menu bar events
- if (part == inMenuBar)
- {
- MovableModalMenus(dPtr, pItem, MenuSelect(gEvent.where));
- break;
- }
-
- // check for outside of our window
- if (!PtInRgn(gEvent.where, ((WindowPeek)dPtr)->strucRgn))
- {
- SysBeep(1);
- gEvent.what = nullEvent;
- }
-
- // drag the window around
- if ( (part == inDrag) && (whichWindow == dPtr) )
- {
- Rect tempRect = (**GetGrayRgn()).rgnBBox;
-
- DragWindow(GetDialogWindow(dPtr), gEvent.where, &tempRect);
- gEvent.what = nullEvent;
- }
- }
-
- // check with standard dialog stuff
- {
- DialogRef tempDialog;
-
- if ( IsDialogEvent(&gEvent) && DialogSelect(&gEvent, &tempDialog, pItem) )
- break;
- }
-
- // handle updates
- if (gEvent.what == updateEvt)
- {
- HandleEvent(&gEvent);
- break;
- }
- } while (true);
-
- SetPort(curPort);
- }
-
- } // MovableModalDialog
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- void BeginMovableModal(void)
- {
- DialogRef dPtr = FrontWindow();
- WindowRef nextWindow = GetNextWindow(dPtr);
-
- if (nextWindow)
- DoActivate(nextWindow, false);
- AdjustMenus(GetDialogWindow(dPtr), (GetDialogKeyboardFocusItem(dPtr) > 0), false);
-
- } // BeginMovableModal
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- void EndMovableModal(void)
- {
- WindowRef nextWindow = FrontWindow();
-
- AdjustMenus(nextWindow, true, false);
- if (nextWindow)
- DoActivate(nextWindow, true);
-
- } // EndMovableModal
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- short ConductFindOrReplaceDialog(short dialogID)
- {
- DialogRef dPtr;
- short hit;
-
- dPtr = GetNewDialog(dialogID, nil, (WindowRef)-1);
- if (dPtr)
- {
- short kind;
- Rect box;
- Handle item;
-
- // standard default behavior
- SetDialogDefaultItem(dPtr, ok);
- SetDialogCancelItem (dPtr, cancel);
- SetDialogTracksCursor(dPtr, true);
-
- // Find string
- GetDialogItem(dPtr, iFindEdit, &kind, &item, &box);
- SetDialogItemText(item, gFindString);
-
- // check boxes
- GetDialogItem(dPtr, iCaseSensitive, &kind, &item, &box);
- SetControlValue((ControlRef)item, gCaseSensitive);
- GetDialogItem(dPtr, iWrapAround, &kind, &item, &box);
- SetControlValue((ControlRef)item, gWrapAround);
-
- if (dialogID == kReplaceWindowID)
- {
- // Replace string
- GetDialogItem(dPtr, iReplaceEdit, &kind, &item, &box);
- SetDialogItemText(item, gReplaceString);
- }
-
- // select the search text by default
- SelectDialogItemText(dPtr, iFindEdit, 0, 32767);
-
- // and away we go!
- ShowWindow(GetDialogWindow(dPtr));
- BeginMovableModal();
-
- do
- {
- MovableModalDialog(nil, &hit);
- switch (hit)
- {
- case iCaseSensitive:
- case iWrapAround:
- GetDialogItem(dPtr, hit, &kind, &item, &box);
- SetControlValue((ControlRef)item, 1-GetControlValue((ControlRef)item));
- break;
- }
- } while ( (hit != ok) && (hit != cancel) && (hit != iReplaceAll) );
-
- if (hit != cancel)
- {
- // Find string
- GetDialogItem(dPtr, iFindEdit, &kind, &item, &box);
- GetDialogItemText(item, gFindString);
-
- // check boxes
- GetDialogItem(dPtr, iCaseSensitive, &kind, &item, &box);
- gCaseSensitive = GetControlValue((ControlRef)item);
- GetDialogItem(dPtr, iWrapAround, &kind, &item, &box);
- gWrapAround = GetControlValue((ControlRef)item);
-
- if (dialogID == kReplaceWindowID)
- {
- // Replace string
- GetDialogItem(dPtr, iReplaceEdit, &kind, &item, &box);
- GetDialogItemText(item, gReplaceString);
- }
- }
-
- DisposeDialog(dPtr);
- EndMovableModal();
- }
-
- return(hit);
-
- } // ConductFindOrReplaceDialog
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- void SetWatchCursor(void)
- {
- CursHandle theWatch;
-
- theWatch = GetCursor(watchCursor);
- if (theWatch)
- {
- char oldState;
-
- oldState = HGetState((Handle) theWatch);
- HLock((Handle) theWatch);
- SetCursor(*theWatch);
- HSetState((Handle) theWatch, oldState);
- }
-
- } // SetWatchCursor
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- void LongRectToRect(LongRect* longRect, Rect *rect)
- {
- rect->top = longRect->top;
- rect->left = longRect->left;
- rect->bottom = longRect->bottom;
- rect->right = longRect->right;
-
- } // LongRectToRect
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- void RectToLongRect(Rect *rect, LongRect *longRect)
- {
- longRect->top = rect->top;
- longRect->left = rect->left;
- longRect->bottom = rect->bottom;
- longRect->right = rect->right;
-
- } // RectToLongRect
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- void GetPICTRectangleAt72dpi(PicHandle hPicture, Rect *pictureRect)
- {
- typedef struct FixedRect {
- Fixed left;
- Fixed top;
- Fixed right;
- Fixed bottom;
- } FixedRect;
-
- typedef struct {
- Picture pictInfo;
- unsigned short versionOp; // 0x1101
- Byte opCodes[1];
- } PICTHeaderVer1;
-
- typedef struct {
- Picture pictInfo;
- unsigned short versionOp; // 0x0011
- unsigned short versionOp2; // 0x02ff
- unsigned short headerOp; // 0x0c00
- unsigned short version; // 0xffff
- unsigned short version2; // 0xffff
- FixedRect pictBounds;
- unsigned long reserved;
- unsigned short opCodes[1];
- } PICTHeaderVer2;
-
- typedef struct {
- Picture pictInfo;
- unsigned short versionOp; // 0x0011
- unsigned short versionOp2; // 0x02ff
- unsigned short headerOp; // 0x0c00
- unsigned short version; // 0xfffe
- unsigned short reserved; // 0x0000
- Fixed hRes;
- Fixed vRes;
- Rect pictBounds;
- unsigned long reserved2;
- unsigned short opCodes[1];
- } PICTHeaderVer2Ext;
-
- Fixed hRes, vRes;
- PICTHeaderVer1* pPict = (PICTHeaderVer1*) *hPicture;
-
- hRes = vRes = ff(72); // assume 72 dpi
-
- if (pPict->versionOp == 0x0011)
- {
- // Version 2 PICT
-
- PICTHeaderVer2* pPict2 = (PICTHeaderVer2*) pPict;
-
- if (pPict2->version == 0xfffe)
- {
- // Extended Version 2
- PICTHeaderVer2Ext* pPict2ext = (PICTHeaderVer2Ext*) pPict;
- hRes = pPict2ext->hRes;
- vRes = pPict2ext->vRes;
- }
- }
-
- hRes = FixDiv(hRes, ff(72));
- vRes = FixDiv(vRes, ff(72));
- pictureRect->left = Fix2Long(FixDiv( ff((**hPicture).picFrame.left), hRes ));
- pictureRect->right = Fix2Long(FixDiv( ff((**hPicture).picFrame.right), hRes ));
- pictureRect->top = Fix2Long(FixDiv( ff((**hPicture).picFrame.top), vRes ));
- pictureRect->bottom = Fix2Long(FixDiv( ff((**hPicture).picFrame.bottom), vRes ));
-
- } // GetPICTRectangleAt72dpi
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- static WindowDataPtr GetWindowInfo(WindowRef pWindow)
- {
- WindowDataPtr result = nil;
-
- if (
- (pWindow) &&
- (GetWindowKind(pWindow) == userKind)
- )
- result = (WindowDataPtr) GetWRefCon(pWindow);
-
- return result;
-
- } // GetWindowInfo
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Utility
-
- static short ZeroStringSub(Str255 destString, Str255 subStr)
- // returns number of substitutions performed
- {
- OSErr anErr;
- Handle destHandle = nil;
- Handle subHandle = nil;
- short count = 0;
-
- anErr = PtrToHand(&destString[1], &destHandle, destString[0]);
- if (anErr == noErr)
- {
- anErr = PtrToHand(&subStr[1], &subHandle, subStr[0]);
- if (anErr == noErr)
- {
- count = ReplaceText(destHandle, subHandle, "\p^0"); // error or # of substitutions
-
- destString[0] = GetHandleSize(destHandle);
- BlockMoveData(*destHandle, &destString[1], destString[0]);
- }
- }
-
- DisposeHandle(destHandle);
- DisposeHandle(subHandle);
-
- if (count < 0)
- count = 0; // change error code into count = 0 substitutions
-
- return count;
-
- } // ZeroStringSub
-
- // --------------------------------------------------------------------------------------------------------------
- // SEARCH/REPLACE UTILITY FUNCTIONS
- // --------------------------------------------------------------------------------------------------------------
- static Boolean IsThisTheString(
- Ptr p, // pointer to check
- Str255 searchString, // string to check for
- Boolean isCaseSensitive) // case sensitive check or not
- /*
- Returns true if the supplied string is at the specified offset.
- Otherwise returns false.
- */
- {
- Boolean returnValue = false;
-
- if (isCaseSensitive)
- returnValue = ( IUMagString(p, &searchString[1], searchString[0], searchString[0]) == 0 );
- else
- returnValue = ( IUMagIDString(p, &searchString[1], searchString[0], searchString[0]) == 0 );
-
- return(returnValue);
-
- } // IsThisTheString
-
- // --------------------------------------------------------------------------------------------------------------
-
- Boolean PerformSearch(
- Handle h, // handle to search
- long start, // offset to begin with
- Str255 searchString, // string to search for
- Boolean isCaseSensitive, // case sensitive search
- Boolean isBackwards, // search backwards from starting point
- Boolean isWraparound, // wrap search around from end->begining
- long * pNewStart, // returned new selection start
- long * pNewEnd) // returned new selection end
- /*
- Performs a search on the supplied handle, starting at the provided
- offset. Returns the new selection start and end values, and true
- if the search is successful. Otherwise it returns false.
- */
- {
- char flags;
- Ptr startPtr;
- Ptr endPtr;
- Ptr searchPtr;
- Boolean foundIt = false;
-
- flags = HGetState(h);
- HLock(h);
-
- // back up one when searching backwards, or we'll hit every time on the current
- // character
- if (isBackwards)
- {
- if (start != 0)
- {
- --start;
- }
- else
- {
- if (isWraparound)
- start = GetHandleSize(h);
- else
- return(false);
- }
- }
-
- // determine the bounds of the searching
- startPtr = (*h) + start;
- if ( isWraparound )
- {
- if (isBackwards)
- {
- // go backwards until just after the start, or begining of
- // document is start is the end
- if (start == GetHandleSize(h))
- endPtr = *h;
- else
- endPtr = startPtr + 1;
- }
- else
- {
- // go forwards until just before the start, or to the end
- // of the document is the start is already the begining
- if (start == 0)
- endPtr = *h + GetHandleSize(h);
- else
- endPtr = startPtr - 1;
- }
- }
- else
- {
- if (isBackwards)
- {
- // go back until hit begining of document
- endPtr = *h-1;
- }
- else
- {
- // go forward until hit end of document
- endPtr = *h + GetHandleSize(h);
- }
- }
-
- searchPtr = startPtr;
- while (searchPtr != endPtr)
- {
- if (IsThisTheString(searchPtr, searchString, isCaseSensitive))
- {
- foundIt = true;
- *pNewStart = searchPtr - *h;
- *pNewEnd = *pNewStart + searchString[0];
- break;
- }
-
- if (isBackwards)
- --searchPtr;
- else
- ++searchPtr;
-
- if (isWraparound)
- {
- if (searchPtr < *h)
- searchPtr = *h + GetHandleSize(h);
- if (searchPtr > *h + GetHandleSize(h))
- searchPtr = *h;
- }
- }
-
- HSetState(h, flags);
-
- return(foundIt);
-
- } // PerformSearch
-
- // --------------------------------------------------------------------------------------------------------------
- // SELECTION UTILITY ROUTINES
- // --------------------------------------------------------------------------------------------------------------
- void DrawSelection(WindowDataPtr pData, Rect *pSelection, short * pPhase, Boolean bumpPhase)
- {
- if (!EmptyRect(pSelection) )
- {
- RgnHandle oldClip = NewRgn();
- Pattern aPattern;
- Rect newClip;
-
-
- if (
- (bumpPhase) &&
- (MOVESELECTION(TickCount()) )
- )
- {
- if ((++(*pPhase)) > 7 )
- *pPhase = 1;
- }
-
- // setup for drawing in this window
- SetPort((GrafPtr) pData);
- GetClip(oldClip);
- PenMode(notPatXor);
-
- // offset the draw area (SetOrigin a must to preserve pattern appearence)
- // and the clip area to avoid stepping on the scroll bars
- SetOrigin(GetControlValue(pData->hScroll), GetControlValue(pData->vScroll));
- newClip = pData->contentRect;
- OffsetRect(&newClip, GetControlValue(pData->hScroll), GetControlValue(pData->vScroll));
- ClipRect(&newClip);
-
- // do the draw
- GetIndPattern(&aPattern, kPatternListID, (*pPhase)+1);
- PenPat(&aPattern);
- FrameRect(pSelection);
- SetOrigin(0, 0);
-
- // restore the old port settings
- SetClip(oldClip);
- DisposeRgn(oldClip);
- PenNormal();
-
- }
-
- } // DrawSelection
-
- // --------------------------------------------------------------------------------------------------------------
- OSErr SelectContents(WindowRef pWindow, WindowDataPtr pData, EventRecord *pEvent, Rect *pSelection, Rect *pContent, short *pPhase)
- {
-
- OSErr anErr = noErr;
- Point clickPoint = pEvent->where;
- Point currentPoint;
- Boolean didJustScroll;
- ControlRef theControl;
-
- GlobalToLocal(&clickPoint);
- if (FindControl(clickPoint, pWindow, &theControl) == 0)
- {
-
- // move the click point into the proper range
- clickPoint.h += GetControlValue(pData->hScroll);
- clickPoint.v += GetControlValue(pData->vScroll);
-
- // if the shift key is held down then the selection starts from
- // a preexisting point such that we are doing an expand/contract
- // of the original selection
- if (pEvent->modifiers & shiftKey)
- {
- if (clickPoint.h < pSelection->right)
- clickPoint.h = pSelection->right;
- else
- clickPoint.h = pSelection->left;
-
- if (clickPoint.v < pSelection->bottom)
- clickPoint.v = pSelection->bottom;
- else
- clickPoint.v = pSelection->top;
- }
-
- while (StillDown())
- {
- // get the current mouse
- GetMouse(¤tPoint);
-
- didJustScroll = false;
- // scroll contents if needed
- {
- short deltaH = 0;
- short deltaV = 0;
-
- if (currentPoint.h < 0)
- deltaH = pData->hScrollAmount;
- if (currentPoint.h > qd.thePort->portRect.right)
- deltaH = -pData->hScrollAmount;
- if (currentPoint.v < 0)
- deltaV = pData->vScrollAmount;
- if (currentPoint.v > qd.thePort->portRect.bottom)
- deltaV = -pData->vScrollAmount;
-
- if ( (deltaH != 0) || (deltaV != 0) )
- {
- if (deltaH)
- SetControlAndClipAmount(pData->hScroll, &deltaH);
- if (deltaV)
- SetControlAndClipAmount(pData->vScroll, &deltaV);
-
- DoScrollContent(pWindow, pData, deltaH, deltaV);
-
- didJustScroll = true;
- }
- }
-
- // map mouse into proper range
- currentPoint.h += GetControlValue(pData->hScroll);
- currentPoint.v += GetControlValue(pData->vScroll);
-
- // clip to the document size
- if (currentPoint.h < 0)
- currentPoint.h = 0;
- if (currentPoint.v < 0)
- currentPoint.v = 0;
- if (currentPoint.h > pContent->right)
- currentPoint.h = pContent->right;
- if (currentPoint.v > pContent->bottom)
- currentPoint.v = pContent->bottom;
-
- // draw the new selection if it is time or we are about to
- // exit this loop
- if ((MOVESELECTION(TickCount())) || (!Button()) || (didJustScroll) )
- {
- // first, erase any old selection we might have had
- DrawSelection(pData, pSelection, pPhase, false);
-
- // make a rectangle out of the two points
- pSelection->left = Min(currentPoint.h, clickPoint.h);
- pSelection->right = Max(currentPoint.h, clickPoint.h);
- pSelection->top = Min(currentPoint.v, clickPoint.v);
- pSelection->bottom = Max(currentPoint.v, clickPoint.v);
-
- // draw the new selection
- DrawSelection(pData, pSelection, pPhase, true);
- }
- }
-
- // we handled the selection
- anErr = eActionAlreadyHandled;
- }
-
- return(anErr);
-
- } // SelectContents
-
- // --------------------------------------------------------------------------------------------------------------
- void DragAndDropArea(WindowRef pWindow, WindowDataPtr pData, EventRecord* event, Rect *pFrameRect)
- {
- RgnHandle hilightRgn;
- Rect r;
- DragReference theDrag;
- OSErr anErr = noErr;
-
- if (NewDrag(&theDrag) == noErr)
- {
- if (pData->pDragAddFlavors)
- anErr = (*(pData->pDragAddFlavors)) (pWindow, pData, theDrag);
-
- if (anErr == noErr)
- {
- Rect globalRect = *pFrameRect;
-
- hilightRgn = NewRgn();
- LocalToGlobal(&TopLeft(globalRect));
- LocalToGlobal(&BotRight(globalRect));
- RectRgn(hilightRgn, &globalRect);
- SetDragItemBounds(theDrag, 1, &r);
-
- // turn the region from a fill into a frame
- {
- RgnHandle tempRgn = NewRgn();
-
- CopyRgn(hilightRgn, tempRgn);
- InsetRgn(tempRgn, 1, 1);
- DiffRgn(hilightRgn, tempRgn, hilightRgn);
- DisposeRgn(tempRgn);
- }
-
- TrackDrag(theDrag, event, hilightRgn);
- DisposeDrag(theDrag);
- DisposeRgn(hilightRgn);
- }
- }
-
- } // DragAndDropArea
-
- // --------------------------------------------------------------------------------------------------------------
- // WINDOW UTILITY ROUTINES
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static void CalculateGrowIcon(WindowDataPtr pData, Rect * location)
- {
- if (pData->vScroll)
- location->top = (**pData->vScroll).contrlRect.bottom;
- else
- {
- if (pData->hScroll)
- location->top = (**pData->hScroll).contrlRect.top;
- else
- location->top = pData->theWindow.port.portRect.bottom - 15;
- }
-
- if (pData->hScroll)
- location->left = (**pData->hScroll).contrlRect.right;
- else
- {
- if (pData->vScroll)
- location->left = (**pData->vScroll).contrlRect.left;
- else
- location->left = pData->theWindow.port.portRect.right - 15;
- }
-
- location->right = location->left + 16;
- location->bottom = location->top + 16;
-
- } // CalculateGrowIcon
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- OSErr AdjustScrollBars(WindowRef pWindow,
- Boolean moveControls, // might the controls have moved?
- Boolean didResize, // did we just resize the window?
- Boolean *needInvalidate) // does the caller need to invalidate contents as a result?
- {
- OSErr anErr = noErr;
- LongRect docRect;
- WindowDataPtr pData = GetWindowInfo(pWindow);
- Rect growIconRect;
-
- if (needInvalidate)
- *needInvalidate = false;
-
- if (pData)
- {
- short oldHMax, oldVMax;
- short oldHValue, oldVValue;
-
- // cache current values, we'll force an update if we needed to change em!
- if (pData->hScroll)
- {
- oldHMax = GetControlMaximum(pData->hScroll);
- oldHValue = GetControlValue(pData->hScroll);
- }
- if (pData->vScroll)
- {
- oldVMax = GetControlMaximum(pData->vScroll);
- oldVValue = GetControlValue(pData->vScroll);
- }
-
- // if we have a grow box but not all controls we have to invalidate the grow bar areas
- // by caclulating them
- if ( (didResize) && (pData->hasGrow) )
- {
- // if we regrow without any scroll bars, we need to update the content area
- if ( (needInvalidate) && (pData->hScroll == nil) && (pData->vScroll == nil) )
- *needInvalidate = true;
-
- // invalidate old grow bar areas
- if (pData->vScroll == nil)
- {
- growIconRect = GetWindowPort(pWindow)->portRect;
- growIconRect.left = pData->contentRect.right;
- InvalRect(&growIconRect);
- }
- if (pData->hScroll == nil)
- {
- growIconRect = GetWindowPort(pWindow)->portRect;
- growIconRect.top = pData->contentRect.bottom;
- InvalRect(&growIconRect);
- }
-
- // invalidate new grow bar areas
- if (pData->vScroll == nil)
- {
- growIconRect = GetWindowPort(pWindow)->portRect;
- growIconRect.left = growIconRect.right - kScrollBarSize;
- InvalRect(&growIconRect);
- }
- if (pData->hScroll == nil)
- {
- growIconRect = GetWindowPort(pWindow)->portRect;
- growIconRect.top = growIconRect.bottom - kScrollBarSize;
- InvalRect(&growIconRect);
- }
- }
-
- // if the controls need moving, recalculate the visible area
- if (moveControls)
- {
- pData->contentRect = GetWindowPort(pWindow)->portRect;
- if ((pData->hScroll) || (pData->hasGrow) )
- pData->contentRect.bottom -= kScrollBarSize;
- if ((pData->vScroll) || (pData->hasGrow) )
- pData->contentRect.right -= kScrollBarSize;
- }
-
- // before doing anything, make the controls invisible
- if (pData->hScroll)
- (**pData->hScroll).contrlVis = 0;
- if (pData->vScroll)
- (**pData->vScroll).contrlVis = 0;
-
- // based on document and visiable area, adjust possible control values
- if ( (pData->pGetDocumentRect) && ((pData->hScroll) || (pData->vScroll)) )
- {
- // let the object calc the size and content if it wishes to
- anErr = (*(pData->pGetDocumentRect)) (pWindow, pData, &docRect, false);
- if (anErr == noErr)
- {
- short amountOver;
- short newMax;
-
- amountOver = (docRect.right - docRect.left) - (pData->contentRect.right - pData->contentRect.left);
- if (
- (pData->hScroll) &&
- (amountOver > 0)
- )
- newMax = amountOver;
- else
- newMax = 0;
-
- if (pData->hScroll)
- {
- if (GetControlValue(pData->hScroll) > newMax)
- {
- if (needInvalidate)
- *needInvalidate = true;
- }
- SetControlMaximum(pData->hScroll, newMax);
- }
-
- amountOver = (docRect.bottom - docRect.top) - (pData->contentRect.bottom - pData->contentRect.top);
- if (
- (pData->vScroll) &&
- (amountOver > 0)
- )
- newMax = amountOver;
- else
- newMax = 0;
-
- if (pData->vScroll)
- {
- if (GetControlValue(pData->vScroll) > newMax)
- {
- if (needInvalidate)
- *needInvalidate = true;
- }
- SetControlMaximum(pData->vScroll, newMax);
- }
- }
- }
-
- // then, if the controls need moving, we move them and inval the old
- // and new locations
- if (moveControls)
- {
- // if we have grow box we invalidate the old grow location
- if ( pData->hasGrow)
- {
- CalculateGrowIcon(pData, &growIconRect);
- InvalRect(&growIconRect);
- }
-
- if (pData->hScroll)
- {
- short widthAdjust;
-
- if ((pData->vScroll) || (pData->hasGrow))
- widthAdjust = -kGrowScrollAdjust;
- else
- widthAdjust = -1;
-
- growIconRect = (**pData->hScroll).contrlRect;
- InvalRect(&growIconRect);
-
- MoveControl(pData->hScroll, pData->hScrollOffset-1, GetWindowPort(pWindow)->portRect.bottom - kScrollBarSize);
- SizeControl(pData->hScroll, (GetWindowPort(pWindow)->portRect.right -
- GetWindowPort(pWindow)->portRect.left) + widthAdjust - pData->hScrollOffset,
- 16);
-
- growIconRect = (**pData->hScroll).contrlRect;
- InvalRect(&growIconRect);
- }
-
- if (pData->vScroll)
- {
- short heightAdjust;
-
- if ((pData->hScroll) || (pData->hasGrow))
- heightAdjust = -kGrowScrollAdjust;
- else
- heightAdjust = -1;
-
- growIconRect = (**pData->vScroll).contrlRect;
- InvalRect(&growIconRect);
-
- MoveControl(pData->vScroll, GetWindowPort(pWindow)->portRect.right - kScrollBarSize, pData->vScrollOffset-1);
- SizeControl(pData->vScroll, 16,
- (GetWindowPort(pWindow)->portRect.bottom -
- GetWindowPort(pWindow)->portRect.top) + heightAdjust - pData->vScrollOffset);
- growIconRect = (**pData->vScroll).contrlRect;
- InvalRect(&growIconRect);
- }
-
- // if we have scroll bars, update the grow icon
- if ( pData->hasGrow )
- {
- CalculateGrowIcon(pData, &growIconRect);
- InvalRect(&growIconRect);
- }
-
- }
-
- // let the document adjust anything it needs to
- if (pData->pAdjustSize)
- anErr = (*(pData->pAdjustSize)) (pWindow, pData, &didResize);
-
- if ((didResize) && (needInvalidate))
- *needInvalidate = true;
-
-
- if ( ((WindowPeek) pWindow)->hilited )
- {
- // after doing something, make the controls visible
- if (pData->hScroll)
- {
- if ((oldHMax != GetControlMaximum(pData->hScroll)) || (oldHValue != GetControlValue(pData->hScroll)) )
- ShowControl(pData->hScroll);
- else
- (**pData->hScroll).contrlVis = 0xFF;
- }
- if (pData->vScroll)
- {
- if ((oldVMax != GetControlMaximum(pData->vScroll)) || (oldVValue != GetControlValue(pData->vScroll)) )
- ShowControl(pData->vScroll);
- else
- (**pData->vScroll).contrlVis = 0xFF;
- }
- }
-
- }
-
- return anErr;
-
- } // AdjustScrollBars
-
- // --------------------------------------------------------------------------------------------------------------
- // MENU UTILITY ROUTINES
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- Boolean CommandToIDs(short commandID, short * menuID, short *itemID)
- {
-
- short ** commandHandle;
- short whichMenu;
- short oldResFile = CurResFile();
- Boolean returnValue = false;
-
- UseResFile(gApplicationResFile);
- for (whichMenu = mApple; whichMenu <= mLastMenu; whichMenu++)
- {
- commandHandle = (short**) Get1Resource('MCMD', whichMenu);
- if (commandHandle)
- {
- short * pCommands = *commandHandle;
- short commandIndex;
- short numCommands = pCommands[0];
-
- for (commandIndex = 1; commandIndex <= numCommands; ++commandIndex)
- if (pCommands[commandIndex] == commandID)
- {
- *menuID = whichMenu;
- *itemID = commandIndex;
-
- returnValue = (commandIndex == numCommands);
- }
- }
- }
-
- UseResFile(oldResFile);
-
- return returnValue;
-
- } // CommandToIDs
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- Boolean IsCommandEnabled(short commandID)
- /*
- returns true if a given command is currently enabled
- */
- {
- short whichMenu, whichItem;
- MenuHandle menu;
-
- CommandToIDs(commandID, &whichMenu, &whichItem);
- menu = GetMenuHandle(whichMenu);
-
- if ((**menu).enableFlags & (1 << whichItem))
- return(true);
-
- return(false);
-
- } // IsCommandEnabled
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- void EnableCommand(short commandID)
- /*
- Given a command ID, enables the first menu item with that command ID.
-
- If the command table for a given menu is less than the number of items in the menu,
- and the command being enabled is the last item in the command table, then all
- items from there on down are also enabled. This is useful for menus that get
- appended to, such as the desk accessory list, font list, or speaking voices list.
- */
- {
- short whichMenu;
- short whichItem;
-
- if (CommandToIDs(commandID, &whichMenu, &whichItem))
- {
- short i;
- MenuHandle menu = GetMenuHandle(whichMenu);
-
- if (menu)
- {
- short numItems = CountMItems(menu);
-
- for (i = whichItem; i <= numItems; ++i)
- EnableItem(menu, i);
- }
- }
- else
- {
- MenuHandle menu = GetMenuHandle(whichMenu);
-
- if (menu)
- EnableItem(menu, whichItem);
- }
-
- } // EnableCommand
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- void ChangeCommandName(short commandID, short resourceID, short resourceIndex)
- {
- short whichMenu;
- short whichItem;
- MenuHandle menu;
-
- // figure out how this command maps into the menu bar
- CommandToIDs(commandID, &whichMenu, &whichItem);
- menu = GetMenuHandle(whichMenu);
-
- // then make this item into the requested new string
- {
- Str255 theString;
-
- GetIndString(theString, resourceID, resourceIndex);
- SetMenuItemText(menu, whichItem, theString);
- }
-
- } // ChangeCommandName
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- void EnableCommandCheck(short commandID, Boolean check)
- {
-
- short whichMenu;
- short whichItem;
-
- if (CommandToIDs(commandID, &whichMenu, &whichItem))
- {
- short i;
- MenuHandle menu = GetMenuHandle(whichMenu);
- short numItems = CountMItems(menu);
-
- for (i = whichItem; i <= numItems; ++i)
- {
- EnableItem(menu, i);
- CheckItem(menu, i, check);
- }
- }
- else
- {
- MenuHandle menu = GetMenuHandle(whichMenu);
-
- EnableItem(menu, whichItem);
- CheckItem(menu, whichItem, check);
- }
-
- } // EnableCommandCheck
-
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- void EnableCommandCheckStyle(short commandID, Boolean check, short style)
- {
-
- short whichMenu;
- short whichItem;
-
- if (CommandToIDs(commandID, &whichMenu, &whichItem))
- {
- short i;
- MenuHandle menu = GetMenuHandle(whichMenu);
- short numItems = CountMItems(menu);
-
- for (i = whichItem; i <= numItems; ++i)
- {
- EnableItem(menu, i);
- CheckItem(menu, i, check);
- SetItemStyle(menu, i, style);
- }
- }
- else
- {
- MenuHandle menu = GetMenuHandle(whichMenu);
-
- EnableItem(menu, whichItem);
- CheckItem(menu, whichItem, check);
- SetItemStyle(menu, whichItem, style);
- }
-
- } // EnableCommandCheckStyle
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- void AdjustMenus(WindowRef pWindow, Boolean editDialogs, Boolean forceTitlesOn)
- {
- Boolean wasEnabled[mNumberMenus]; // Old state of menus
- short whichMenu; // for stepping through menus
- MenuHandle menu; // for reading in menu IDs
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- // Step through all of the menus
- for (whichMenu = mApple; whichMenu <= mLastMenu; whichMenu++)
- {
- // Save the old state of the menu title
- menu = GetMenuHandle(whichMenu);
- if (menu) // because contents menu may not be around
- {
- if (forceTitlesOn)
- wasEnabled[mLastMenu - whichMenu] = false;
- else
- wasEnabled[mLastMenu - whichMenu] = (((**menu).enableFlags && 1) == 1);
-
- // Disable the entire menu
- (**menu).enableFlags = 0;
- }
- }
-
- // select all, unless someone else changes it
- ChangeCommandName(cSelectAll, kMiscStrings, iSelectAllCommand);
-
- // if we have NO windows, or the current window is one we understand
- if ((pWindow == nil) || (pData))
- {
- // enable the default commands
- EnableCommand(cAbout);
- EnableCommand(cDeskAccessory);
-
- EnableCommand(cNew);
- EnableCommand(cOpen);
- EnableCommand(cQuit);
-
- EnableCommand(cShowClipboard);
- }
- else
- {
- // it's printing or a dialog, so enable cut/copy/paste
- if (editDialogs)
- {
- EnableCommand(cCut);
- EnableCommand(cCopy);
- EnableCommand(cPaste);
- EnableCommand(cClear);
- }
-
- // and desk accs too!
- EnableCommand(cDeskAccessory);
-
- }
-
- if ( (pWindow) && (pData) )
- {
- // all windows can be closed
- if (FrontWindow())
- EnableCommand(cClose);
-
- // changed documents can be saved, but only if the file is open for write
- if ( (pData->changed) &&
- ((pData->isWritable) || (pData->dataRefNum == -1)) )
- EnableCommand(cSave);
-
- // objects with a print method can be printed and page setup-ed
- if (pData->pPrintPage)
- {
- EnableCommand(cPrint);
- EnableCommand(cPageSetup);
- EnableCommand(cPrintOneCopy);
- }
-
- // let object enable anything else that needs to be enabled
- if (pData->pAdjustMenus)
- (*(pData->pAdjustMenus)) (pWindow, pData);
- }
-
- // Now determine if any of the menus have changed state
- {
- Boolean gotToRedraw = false;
-
- for (whichMenu = mApple; whichMenu <= mLastMenu; ++whichMenu)
- {
- menu = GetMenuHandle(whichMenu);
-
- if (menu) // because contents menu may not be around
- {
- // If any of the menu is enabled
- if ((**menu).enableFlags != 0)
- {
- // Make sure to turn on the menu title
- (**menu).enableFlags |= 1;
- }
-
- /* If this new state is different than the saved state, then the menu bar
- will need to be redrawn */
- if (wasEnabled[mLastMenu - whichMenu] != ((**menu).enableFlags && 1))
- {
- gotToRedraw = true;
- }
- }
- }
-
- // And if any titles have changed state, redraw them
- if (gotToRedraw)
- DrawMenuBar();
- }
-
- } // AdjustMenus
-
- // --------------------------------------------------------------------------------------------------------------
- // PRINTING UTILITY ROUTINES
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Printing
-
- Boolean IsSomewhereInRectangle(gxRectangle *pContainer, gxRectangle *pShape)
- /*
- Calculates this by saying the rectangle doesn't intersect at ALL,
- and then NOTs that expression.
- */
- {
- return
- (!(
- pShape->top > pContainer->bottom ||
- pShape->bottom < pContainer->top ||
- pShape->left > pContainer->right ||
- pShape->right < pContainer->left
- ));
-
- } // IsSomewhereInRectangle
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Printing
-
- static OSErr SimpleCatchShape(gxShape newShape, CatchRefCon * pRefCon)
- {
- Boolean addShape = false;
- gxGraphicsError anErr;
-
- // did the user abort printing?
- anErr = GXGetJobError(pRefCon->theJob);
- if (anErr != noErr)
- return anErr;
-
- switch (GXGetShapeType(newShape))
- {
-
- // if we have a layout, turn off justification so that we can get
- // better looking morph effects, and also enable the default features
- // of the layout. However, we can only do this if the layout is
- // in a script system where the translation wasn't done by a Print Action Hook.
- // For now, this means only smRoman styles.
- case gxLayoutType:
- if (pRefCon->doLayout)
- {
- Boolean enableLayout = pRefCon->doLayout;
-
- gxStyle * theStyles;
- long styleCount, index;
-
- GXGetLayout(newShape, nil,
- &styleCount, nil, nil, // style runs
- nil, nil, nil, // run levels
- nil, nil);
- theStyles = (gxStyle*) NewPtr(sizeof(gxStyle)*styleCount);
- if (theStyles)
- {
- GXGetLayout(newShape, nil,
- &styleCount, nil, theStyles, // style runs
- nil, nil, nil, // run levels
- nil, nil);
-
- enableLayout = true;
- for (index = 0; index < styleCount; ++index)
- {
- gxFontScript theScript;
- gxFontPlatform thePlatform = GXGetStyleEncoding(theStyles[index], &theScript, nil);
-
- if ((thePlatform != gxMacintoshPlatform) || (theScript != gxRomanScript))
- enableLayout = false;
- }
-
- if (enableLayout)
- for (index = 0; index < styleCount; ++index)
- {
- gxRunControls theControls;
-
- // re-enable run control features
- GXGetStyleRunControls(theStyles[index], &theControls);
- theControls.flags = 0;
- theControls.track = 0;
- theControls.hangingInhibitFactor = 0;
- theControls.kerningInhibitFactor = 0;
- GXSetStyleRunControls(theStyles[index], &theControls);
-
- // and turn back on default features
- GXSetStyleRunFeatures(theStyles[index], 0, nil);
- }
-
- DisposePtr((Ptr) theStyles);
- }
-
- if ( (enableLayout) && (GetSysDirection() == 0) )
- {
- // turn off justification
- {
- gxLayoutOptions layoutOptions;
-
- // get the current layout options
- layoutOptions.baselineRec = nil;
- GXGetLayout(newShape, nil,
- nil, nil, nil, // style runs
- nil, nil, nil, // run levels
- &layoutOptions, nil);
-
- // setting width to zero allows lines to float, but causes multi-styled
- // lines (separate layouts from the translation process) to run into
- // one another, so we can't do that
- //layoutOptions.width = 0;
- layoutOptions.just = gxNoJustification;
- GXSetLayout(newShape,
- 0, nil, nil, // text runs
- 0, nil, nil, // style runs
- 0, nil, nil, // run levels
- &layoutOptions, nil);
- }
-
- // un-clip the shape left and right so we can see things like hanging puncs.
- {
- gxShape newClip;
- gxRectangle bounds;
-
- newClip = GXGetShapeClip(newShape);
- GXGetShapeLocalBounds(newClip, &bounds);
- GXDisposeShape(newClip);
-
- bounds.left = gxNegativeInfinity;
- bounds.right = gxPositiveInfinity;
- newClip = GXNewRectangle(&bounds);
- GXSetShapeClip(newShape, newClip);
- GXDisposeShape(newClip);
- }
- }
-
- }
-
- // if we aren't forming layouts, we'll go ahead and check for this being on
- // the shape. But for pure text, we'll just always add the text. TextEdit
- // is pretty good about pre-clipping for us.
- if (!pRefCon->doLayout)
- {
- gxRectangle bounds;
-
- GXGetShapeLocalBounds(newShape, &bounds);
- if (IsSomewhereInRectangle(&pRefCon->thePageRectangle, &bounds))
- addShape = true;
- }
- else
- addShape = true;
- break;
-
- // never add these for text case
- case gxRectangleType:
- if (!pRefCon->doLayout)
- addShape = true;
- break;
-
- // always add these shapes if we see any because we don't know how to filter them
- case gxEmptyType:
- case gxFullType:
- case gxPictureType:
- addShape = true;
- break;
-
- default:
- {
- gxRectangle bounds;
-
- GXGetShapeLocalBounds(newShape, &bounds);
- if (IsSomewhereInRectangle(&pRefCon->thePageRectangle, &bounds))
- addShape = true;
- }
- break;
-
- } // switch
-
- if (addShape)
- GXSetPictureParts(pRefCon->thePage, 0, 0, 1, &newShape, nil, nil, nil); /* Add shape */
-
- GXGetGraphicsError(&anErr);
-
- if (anErr == noErr)
- {
- GXIdleJob(pRefCon->theJob);
- anErr = GXGetJobError(pRefCon->theJob);
- }
-
- return anErr;
-
- } // SimpleCatchShape
-
- #if GENERATINGCFM
- static RoutineDescriptor gSimpleCatchShapeRD = BUILD_ROUTINE_DESCRIPTOR(uppgxShapeSpoolProcInfo, SimpleCatchShape);
- static gxShapeSpoolUPP gSimpleCatchShape = &gSimpleCatchShapeRD;
- #else
- static gxShapeSpoolUPP gSimpleCatchShape = NewgxShapeSpoolProc(SimpleCatchShape);
- #endif
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Printing
-
- static OSErr CompleteSpoolFileMessage( gxSpoolFile theSpoolFile )
- {
- OSErr anErr = noErr;
- Handle hIcon;
- short sourceIcon = 0;
- short docIcon = 132;
- WindowDataPtr pData = GXGetJobRefCon(GXGetJob());
-
- // for some file types, we can supply a nicer icon for the Finder to display
- // within the queue when this document is printing
- switch (pData->originalFileType)
- {
- case 'TEXT':
- case 'sEXT':
- sourceIcon = kTextIcon;
- break;
-
- case 'ttro':
- sourceIcon = kReadOnlyIcon;
- break;
-
- case 'PICT':
- sourceIcon = kPICTIcon;
- break;
- }
-
- if (sourceIcon != 0)
- {
- hIcon = GetResource('ICN#', sourceIcon);
- if (hIcon != nil)
- {
- HNoPurge(hIcon);
- DetachResource(hIcon);
- anErr = Send_GXSpoolResource (theSpoolFile, hIcon, 'ICN#', docIcon);
- }
- nrequire(anErr, SpoolOneBit);
-
- hIcon = GetResource('icl4', sourceIcon);
- if (hIcon != nil)
- {
- HNoPurge(hIcon);
- DetachResource(hIcon);
- anErr = Send_GXSpoolResource (theSpoolFile, hIcon, 'icl4', docIcon);
- }
- nrequire(anErr, SpoolFourBit);
-
- hIcon = GetResource('icl8', sourceIcon);
- if (hIcon != nil)
- {
- HNoPurge(hIcon);
- DetachResource(hIcon);
- anErr = Send_GXSpoolResource (theSpoolFile, hIcon, 'icl8', docIcon);
- }
- nrequire(anErr, SpoolEightBit);
- }
-
- anErr = Forward_GXCompleteSpoolFile( theSpoolFile );
-
- // FALL THROUGH EXCEPTION HANDLING
- SpoolOneBit:
- SpoolFourBit:
- SpoolEightBit:
-
- return anErr;
-
- } // CompleteSpoolFileMessage
-
- #if GENERATINGCFM
- static RoutineDescriptor gCompleteSpoolFileMessageRD = BUILD_ROUTINE_DESCRIPTOR(uppGXCompleteSpoolFileProcInfo, CompleteSpoolFileMessage);
- static GXCompleteSpoolFileUPP gCompleteSpoolFileMessage = &gCompleteSpoolFileMessageRD;
- #else
- static GXCompleteSpoolFileUPP gCompleteSpoolFileMessage = NewGXCompleteSpoolFileProc(CompleteSpoolFileMessage);
- #endif
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Printing
-
- static OSErr PrintingEventMessage(EventRecord *event, Boolean filter)
- {
- OSErr anErr = noErr;
- GrafPtr curPort;
-
- GetPort(&curPort);
- if (filter == false)
- {
- switch ( event->what )
- {
- case mouseDown:
- case keyDown:
- case autoKey:
- break;
-
- case activateEvt:
- case updateEvt:
- default:
- HandleEvent(event);
- break;
- }
- }
-
- anErr = Forward_GXPrintingEvent(event, filter);
- SetPort(curPort);
-
- return anErr;
-
- } // PrintingEventMessage
-
- #if GENERATINGCFM
- static RoutineDescriptor gPrintingEventMessageRD = BUILD_ROUTINE_DESCRIPTOR(uppGXPrintingEventProcInfo, PrintingEventMessage);
- static GXPrintingEventUPP gPrintingEventMessage = &gPrintingEventMessageRD;
- #else
- static GXPrintingEventUPP gPrintingEventMessage = NewGXPrintingEventProc(PrintingEventMessage);
- #endif
-
-
-
- // --------------------------------------------------------------------------------------------------------------
- // FILE UTILITY ROUTINES
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static Boolean BringToFrontIfOpen(FSSpecPtr pSpec)
- {
- WindowRef pWindow;
-
- pWindow = FrontWindow();
- while (pWindow)
- {
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- if (
- (pData) &&
- (pData->fileSpec.vRefNum == pSpec->vRefNum) &&
- (pData->fileSpec.parID == pSpec->parID) &&
- EqualString(pData->fileSpec.name, pSpec->name, false, false)
- )
- {
- SelectWindow(pWindow);
- return true;
- }
-
- pWindow = GetNextWindow(pWindow);
- }
-
- return false;
-
- } // BringToFrontIfOpen
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static Boolean BringToFrontIfExists(ResType windowKind)
- {
- WindowRef pWindow;
-
- pWindow = FrontWindow();
- while (pWindow)
- {
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- if ((pData) && (pData->windowKind == windowKind))
- {
- SelectWindow(pWindow);
- return true;
- }
-
- pWindow = GetNextWindow(pWindow);
- }
-
- return false;
-
- } // BringToFrontIfExists
-
- // --------------------------------------------------------------------------------------------------------------
- // MAIN SIMPLETEXT ROUTINES
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr MakeNewWindow(ResType windowKind, FSSpecPtr fileSpec, OSType fileType, Boolean *pWasAlreadyOpen)
- {
- OSErr anErr = fnfErr;
- PreflightRecord thePreflight;
- PreflightWindowProc pPreflight = nil;
- WindowRef pWindow;
- WindowDataPtr pData;
-
- // require a certain amount of RAM free before we allow the new window to be created
- if (FreeMem() < kRAMNeededForNew)
- anErr = memFullErr;
-
- // <50> if we already have a document open from this file, bring the window to the
- // front and return with no error
- if ( (fileSpec) && (fileType != 'sEXT') && (BringToFrontIfOpen(fileSpec)) )
- {
- if (pWasAlreadyOpen)
- *pWasAlreadyOpen = true;
- anErr = noErr;
- return(anErr);
- }
- if (pWasAlreadyOpen)
- *pWasAlreadyOpen = false;
- if (anErr != fnfErr)
- {
- nrequire(anErr, SanityCheckFailed);
- }
-
- // initialize our behavior
- thePreflight.continueWithOpen = true;
- thePreflight.resourceID = kDefaultWindowID;
- thePreflight.wantHScroll = false;
- thePreflight.wantVScroll = false;
- thePreflight.storageSize = sizeof(WindowDataRecord);
- thePreflight.makeProcPtr = nil;
- thePreflight.openKind = fsRdPerm;
- thePreflight.needResFork = false;
- thePreflight.doZoom = false;
- thePreflight.fileType = fileType;
-
- switch (windowKind)
- {
- case kAboutWindow:
- pPreflight = AboutPreflightWindow;
- break;
-
- case kPICTWindow:
- pPreflight = PICTPreflightWindow;
- break;
-
- case kMovieWindow:
- pPreflight = MoviePreflightWindow;
- break;
-
- case kClipboardWindow:
- pPreflight = ClipboardPreflightWindow;
- break;
-
- case kTextWindow:
- pPreflight = TextPreflightWindow;
- break;
-
- case kGXWindow:
- pPreflight = GXPreflightWindow;
- break;
-
- case kThreeDWindow:
- pPreflight = ThreeDPreflightWindow;
- break;
- }
-
- // preflight the window
- if (pPreflight)
- anErr = (*pPreflight) (&thePreflight);
- nrequire(anErr, PreflightFailed);
-
- if (thePreflight.continueWithOpen)
- {
- // allocate a place for the window
- pData = (WindowDataPtr)NewPtrClear(thePreflight.storageSize);
- anErr = MemError();
- nrequire(anErr, FailedToAllocateWindow);
-
- // then actually create the window
- if (gMachineInfo.theEnvirons.hasColorQD)
- pWindow = (WindowRef)GetNewCWindow(thePreflight.resourceID, pData, (WindowPtr)-1);
- else
- pWindow = (WindowRef)GetNewWindow(thePreflight.resourceID, pData, (WindowPtr)-1);
- if (!pWindow) anErr = memFullErr;
- nrequire(anErr, NewWindowFailed);
- SetWRefCon(pWindow, (long) pData);
-
- // zoom the rectangle to big size on this monitor
- // based upon which scroll bars they want
- {
- Rect rect = GetWindowPort(pWindow)->portRect;
- Rect bigRect;
-
- if (gMachineInfo.theEnvirons.hasColorQD)
- bigRect = (**GetMainDevice()).gdRect;
- else
- bigRect = qd.screenBits.bounds;
- bigRect.top += GetMBarHeight() * 2;
- bigRect.left += 4;
- bigRect.bottom -= 4;
- bigRect.right -= 65;
-
- SetPort((GrafPtr) GetWindowPort(pWindow));
- LocalToGlobal(&TopLeft(rect));
- LocalToGlobal(&BotRight(rect));
-
- if ( (thePreflight.wantHScroll) || (thePreflight.doZoom) )
- {
- rect.left = bigRect.left;
- rect.right = bigRect.right;
- }
-
- if ( (thePreflight.wantVScroll) || (thePreflight.doZoom) )
- {
- rect.top = bigRect.top;
- rect.bottom = bigRect.bottom;
- }
-
- MoveWindow(pWindow, rect.left, rect.top, false);
- SizeWindow(pWindow, rect.right - rect.left, rect.bottom - rect.top, false);
- }
-
- // fill in the default contents of the window
- pData->windowKind = windowKind;
- pData->originalFileType = fileType;
- pData->pMakeWindow = (MakeWindowProc)thePreflight.makeProcPtr;
- pData->resRefNum = -1;
- pData->dataRefNum = -1;
- pData->contentRect = GetWindowPort(pWindow)->portRect;
-
- // make the scroll bars
- {
- Rect controlRect;
-
- if (thePreflight.wantHScroll)
- {
- pData->contentRect.bottom -= kScrollBarSize;
- controlRect = GetWindowPort(pWindow)->portRect;
- controlRect.top = controlRect.bottom - 16;
- if (thePreflight.wantVScroll)
- controlRect.right -= kGrowScrollAdjust;
- OffsetRect(&controlRect, -1, 1);
- pData->hScroll = NewControl(pWindow, &controlRect, "\p", true, 0, 0, 0, scrollBarProc, 0);
- }
- if (thePreflight.wantVScroll)
- {
- pData->contentRect.right -= kScrollBarSize;
- controlRect = GetWindowPort(pWindow)->portRect;
- controlRect.left = controlRect.right - 16;
- if (thePreflight.wantVScroll)
- controlRect.bottom -= kGrowScrollAdjust;
- OffsetRect(&controlRect, 1, -1);
- pData->vScroll = NewControl(pWindow, &controlRect, "\p", true, 0, 0, 0, scrollBarProc, 0);
- }
- }
-
- // got a name? Open the file
- if (fileSpec)
- {
- anErr = FSpOpenDF(fileSpec, thePreflight.openKind, &pData->dataRefNum);
- if (
- ((anErr == afpAccessDenied) || (anErr == opWrErr) || (anErr == permErr) ) &&
- (thePreflight.openKind != fsRdPerm)
- )
- {
- thePreflight.openKind = fsRdPerm;
- pData->isWritable = false;
- anErr = FSpOpenDF(fileSpec, thePreflight.openKind, &pData->dataRefNum);
- }
- else
- pData->isWritable = true;
- nrequire(anErr, FailedToOpenFile);
-
- // okay not to find a resource fork, because some don't have them
- pData->resRefNum = FSpOpenResFile(fileSpec, thePreflight.openKind);
-
- // save the file spec in case someone is interested
- pData->fileSpec = *fileSpec;
- }
-
- if (pData->pMakeWindow)
- {
- Rect oldContent = pData->contentRect;
- anErr = (*(pData->pMakeWindow)) (pWindow, pData);
- if (!EqualRect(&oldContent, &pData->contentRect))
- {
- SizeWindow(pWindow,
- pData->contentRect.right + (pData->vScroll != 0) * kScrollBarSize,
- pData->contentRect.bottom + (pData->hScroll != 0) * kScrollBarSize,
- false);
- }
- }
- nrequire(anErr, FailedMakeWindow);
-
- // got a name? Use it as the window title
- if ( (fileSpec) && (!pData->openAsNew) )
- SetWTitle(pWindow, fileSpec->name);
- else
- {
- if ((gMachineInfo.documentCount == 1) && (pData->windowKind == kTextWindow))
- {
- Str255 tempString;
-
- GetIndString(tempString, kMiscStrings, iFirstNewDocumentTitle); // get the "untitled" string (no number)
- SetWTitle(pWindow, tempString);
- }
- else
- {
- Str255 tempString;
- Str32 numString;
-
- GetWTitle(pWindow, tempString);
- NumToString(gMachineInfo.documentCount, numString);
- (void) ZeroStringSub(tempString, numString);
- SetWTitle(pWindow, tempString);
- }
-
- if (pData->bumpUntitledCount)
- gMachineInfo.documentCount++; // bump count if appropriate for this kind of document
- }
-
- // Make sure the scroll bars are reasonable in size, and move if they must
- AdjustScrollBars(pWindow, true, true, nil);
-
- // finally, if all goes well, we can see the window itself!
- ShowWindow(pWindow);
- }
-
- return noErr;
-
- // EXCEPTION HANDLING
- FailedMakeWindow:
- if (pData->resRefNum != -1)
- CloseResFile(pData->resRefNum);
- if (pData->dataRefNum != -1)
- FSClose(pData->dataRefNum);
-
- FailedToOpenFile:
- CloseWindow(pWindow);
-
- NewWindowFailed:
- DisposePtr((Ptr)pData);
-
- FailedToAllocateWindow:
- PreflightFailed:
- SanityCheckFailed:
- return anErr;
-
- } // MakeNewWindow
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- #define dontSaveChanges 3
-
- #define kVisualDelay 8
-
- static pascal Boolean SaveChangesFilter(DialogRef theDialog, EventRecord *theEvent, short *itemHit)
- {
- if (StdFilterProc(theDialog, theEvent, itemHit))
- return true;
-
- if (theEvent->what == updateEvt)
- {
- HandleEvent(theEvent);
- }
-
- if (theEvent->what == keyDown)
- {
- StringPtr keyEquivs = *GetString(kSaveChangesWindowID);
- unsigned char theKey = theEvent->message & charCodeMask;
-
- if (keyEquivs && (theKey == keyEquivs[1] || theKey == keyEquivs[2]))
- {
- short itemType;
- Rect theRect;
- ControlRef theControl;
- long finalTicks;
-
- GetDialogItem(theDialog, dontSaveChanges, &itemType, (Handle *) &theControl, &theRect);
- HiliteControl(theControl, kControlButtonPart);
- Delay(kVisualDelay, &finalTicks);
- HiliteControl(theControl, 0);
-
- *itemHit = dontSaveChanges;
- return true;
- }
- }
-
- return false;
- }
-
-
- static OSErr DoCloseWindow(WindowRef pWindow)
- {
- OSErr anErr = noErr;
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- if ( (pData) && (pData->changed) )
- {
- short hit;
- Str255 wTitle;
- DialogRef dPtr;
-
- GetWTitle(pWindow, wTitle);
- SetCursor(&qd.arrow);
- ParamText(wTitle, "\p", "\p", "\p");
-
- hit = cancel;
- dPtr = GetNewDialog(kSaveChangesWindowID, nil, (WindowRef)-1);
- if (dPtr)
- {
- SetDialogDefaultItem(dPtr, ok);
- SetDialogCancelItem (dPtr, cancel);
- BeginMovableModal();
- do
- {
- MovableModalDialog(SaveChangesFilter, &hit);
- } while ((hit != dontSaveChanges) && (hit != ok) && (hit != cancel));
-
- DisposeDialog(dPtr);
- EndMovableModal();
- }
- switch (hit)
- {
- case ok:
- anErr = DoCommand(pWindow, cSave, 0);
- if (anErr == eUserCanceled) // redundant?
- gAllDone = false;
- break;
-
- case cancel:
- anErr = eUserCanceled;
- gAllDone = false;
- break;
-
- case dontSaveChanges:
- // don't save, so just close it
- break;
- }
- }
-
- if (anErr == noErr)
- {
- if ( (pData) && (pData->pCloseWindow) )
- {
- // let the object close the window if it wishes to
- anErr = (*(pData->pCloseWindow)) (pWindow, pData);
- }
-
- // otherwise we close it the default way
- if (anErr == noErr)
- {
- if (pData)
- {
- CloseWindow(pWindow);
-
- if (pData->hPrint)
- {
- if (gMachineInfo.haveGX)
- GXDisposeJob( pData->hPrint);
- else
- DisposeHandle((Handle) pData->hPrint);
- }
-
- if (pData->resRefNum != -1)
- CloseResFile(pData->resRefNum);
- if (pData->dataRefNum != -1)
- FSClose(pData->dataRefNum);
- DisposePtr((Ptr) pData);
- }
- }
- }
-
- // If we closed the last window, clean up
- if (FrontWindow() == nil)
- {
- AdjustMenus(nil, true, false);
- gMachineInfo.documentCount = 1; // back to "untitled"
- }
-
- return anErr;
-
- } // DoCloseWindow
-
- #undef dontSaveChanges
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr DetermineWindowTypeOrOpen(
- FSSpecPtr theSpec, OSType theType, // optional input params -- file to open
- OSType *returnedTypeList, short * pNumTypes, // optional input params -- returns list of files
- Boolean *pWasAlreadyOpen) // optional input params -- was file already open
- {
- OSErr anErr = noErr;
- OSType typeList[20];
- OSType docList[20];
- short numTypes;
-
- // use local copies if the input params are nil
- if (returnedTypeList == nil)
- returnedTypeList = &typeList[0];
- if (pNumTypes == nil)
- pNumTypes = &numTypes;
- *pNumTypes = 0;
-
- // Load up all of the file types we know how to handle
- AboutGetFileTypes(returnedTypeList, docList, pNumTypes);
- PICTGetFileTypes(returnedTypeList, docList, pNumTypes);
- MovieGetFileTypes(returnedTypeList, docList, pNumTypes);
- ClipboardGetFileTypes(returnedTypeList, docList, pNumTypes);
- TextGetFileTypes(returnedTypeList, docList, pNumTypes);
- GXGetFileTypes(returnedTypeList, docList, pNumTypes);
- ThreeDGetFileTypes(returnedTypeList, docList, pNumTypes);
-
- if (theSpec != nil)
- {
- short index;
- OSType windowType = '????';
-
- for (index = 0; index < (*pNumTypes); ++index)
- if (theType == returnedTypeList[index])
- windowType = docList[index];
-
- if (windowType != '????')
- {
-
- if ( (theType == 'TEXT') || (theType == 'sEXT') )
- {
- FInfo theInfo;
-
- FSpGetFInfo(theSpec, &theInfo);
- if ((theInfo.fdFlags & kIsStationary) != 0)
- theType = 'sEXT';
- else
- theType = 'TEXT';
- }
-
- anErr = MakeNewWindow(windowType, theSpec, theType, pWasAlreadyOpen);
- }
- else
- anErr = eDocumentWrongKind;
- }
-
-
- return anErr;
-
- } // DetermineWindowTypeOrOpen
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- // Handle update/activate events behind Standard File
- static pascal Boolean OpenDialogFilter(DialogRef theDialog, EventRecord *theEvent,
- short *itemHit, void *myDataPtr)
- {
- #pragma unused(myDataPtr)
-
- // Pass updates through (Activates are tricky...was mucking with Apple menu & thereby
- // drastically changing how the system handles the menu bar during our alert)
- if ( (theEvent->what == updateEvt) && (theEvent->message != (long)theDialog) )
- HandleEvent(theEvent);
-
- if (StdFilterProc(theDialog, theEvent, itemHit))
- return(true);
-
- return(false);
-
- } // OpenDialogFilter
-
- #if GENERATINGCFM
- static RoutineDescriptor gOpenDialogFilterRD = BUILD_ROUTINE_DESCRIPTOR(uppModalFilterYDProcInfo, OpenDialogFilter);
- static ModalFilterYDUPP gOpenDialogFilter = &gOpenDialogFilterRD;
- #else
- static ModalFilterYDUPP gOpenDialogFilter = NewModalFilterYDProc(OpenDialogFilter);
- #endif
-
-
- static OSErr DoOpenWindow(void)
- {
- OSErr anErr = noErr;
- short numTypes;
- OSType typeList[20];
- StandardFileReply sfReply;
- Point thePoint = { -1, -1 };
-
- DetermineWindowTypeOrOpen(nil, '????', &typeList[0], &numTypes, nil);
-
- if (gMachineInfo.haveQuickTime)
- {
- CustomGetFilePreview(nil, numTypes, typeList, &sfReply, 0, thePoint, nil, gOpenDialogFilter, nil, nil, nil);
- }
- else
- {
- CustomGetFile(nil, numTypes, typeList, &sfReply, 0, thePoint, nil, gOpenDialogFilter, nil, nil, nil);
- }
-
- if (sfReply.sfGood)
- {
- SetWatchCursor();
-
- anErr = DetermineWindowTypeOrOpen(&sfReply.sfFile, sfReply.sfType, &typeList[0], &numTypes, nil);
-
- SetCursor(&qd.arrow);
- }
-
- return anErr;
-
- } // DoOpenWindow
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr DoUpdateWindow(WindowRef pWindow)
- {
- OSErr anErr = noErr;
- WindowDataPtr pData = GetWindowInfo(pWindow);
- GrafPtr curPort;
-
- // only handle updates for windows we know about
- if (pData)
- {
- GetPort(&curPort);
- SetPort((GrafPtr)GetWindowPort(pWindow));
- BeginUpdate(pWindow);
-
- if (pData->pUpdateWindow)
- anErr = (*(pData->pUpdateWindow)) (pWindow, pData);
-
- EndUpdate(pWindow);
- SetPort(curPort);
- }
-
- return anErr;
-
- } // DoUpdateWindow
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- OSErr DoScrollContent(WindowRef pWindow, WindowDataPtr pData, short deltaH, short deltaV)
- {
- OSErr anErr = noErr;
-
- if ((deltaH) || (deltaV))
- {
- // if we have a balloon displayed, update before scrolling anything
- if (HMIsBalloon())
- DoUpdateWindow(pWindow);
-
- if ((pData) && (pData->pScrollContent))
- anErr = (*(pData->pScrollContent)) (pWindow, pData, deltaH, deltaV);
-
- if (anErr == noErr)
- {
- RgnHandle invalidRgn = NewRgn();
-
- ScrollRect(&pData->contentRect, deltaH, deltaV, invalidRgn);
- InvalRgn(invalidRgn);
- DisposeRgn(invalidRgn);
-
- DoUpdateWindow(pWindow);
- }
- }
-
- return anErr;
-
- } // DoScrollContent
-
- // --------------------------------------------------------------------------------------------------------------
- // BEGIN SCROLL ACTION PROCS
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- void SetControlAndClipAmount(ControlRef control, short * amount)
- {
- short value, max;
-
- value = GetControlValue(control); /* get current value */
- max = GetControlMaximum(control); /* and maximum value */
- *amount = value - *amount;
- if ( *amount < 0 )
- *amount = 0;
- else
- {
- if ( *amount > max )
- *amount = max;
- }
- SetControlValue(control, *amount);
- *amount = value - *amount; /* calculate the real change */
-
- } // SetControlAndClipAmount
-
- // --------------------------------------------------------------------------------------------------------------
- static pascal void VActionProc(ControlRef control, short part)
- {
- if (part != 0)
- {
- WindowRef pWindow = (**control).contrlOwner;
- WindowDataPtr pData = GetWindowInfo(pWindow);
- short amount = 0;
-
- switch (part)
- {
- case kControlUpButtonPart:
- amount = pData->vScrollAmount;
- break;
-
- case kControlDownButtonPart:
- amount = -pData->vScrollAmount;
- break;
-
- // vertical page scrolling should be a multiple of the incremental scrolling -- so that
- // we avoid half-lines of text at the bottom of pages.
-
- // More generically, if there was a method for dealing with text scrolling by a non-constant
- // amount, this would be better -- but SimpleText currently doesn't have a framework to allow
- // the document object to override the scroll amount dynamically. Maybe something to add in
- // the future.
- case kControlPageUpPart:
- amount = (((pData->contentRect.bottom - pData->contentRect.top) / pData->vScrollAmount)-1) * pData->vScrollAmount;
- if (amount == 0)
- amount = pData->contentRect.bottom - pData->contentRect.top;
- break;
-
- case kControlPageDownPart:
- amount = (((pData->contentRect.top - pData->contentRect.bottom) / pData->vScrollAmount)+1) * pData->vScrollAmount;
- if (amount == 0)
- amount = pData->contentRect.top - pData->contentRect.bottom;
- break;
- }
-
- SetControlAndClipAmount(control, &amount);
- if (amount != 0)
- DoScrollContent(pWindow, pData, 0, amount);
- }
-
- } // VActionProc
-
- #if GENERATINGCFM
- static RoutineDescriptor gVActionProcRD = BUILD_ROUTINE_DESCRIPTOR(uppControlActionProcInfo, VActionProc);
- static ControlActionUPP gVActionProc = &gVActionProcRD;
- #else
- static ControlActionUPP gVActionProc = VActionProc;
- #endif
-
- // --------------------------------------------------------------------------------------------------------------
- static pascal void HActionProc(ControlRef control, short part)
- {
- if (part != 0)
- {
- WindowRef pWindow = (**control).contrlOwner;
- WindowDataPtr pData = GetWindowInfo(pWindow);
- short amount = 0;
-
- switch (part)
- {
- case kControlUpButtonPart:
- amount = pData->hScrollAmount;
- break;
-
- case kControlDownButtonPart:
- amount = -pData->hScrollAmount;
- break;
-
- case kControlPageUpPart:
- amount = pData->contentRect.right - pData->contentRect.left;
- break;
-
- case kControlPageDownPart:
- amount = pData->contentRect.left - pData->contentRect.right;
- break;
- }
-
- SetControlAndClipAmount(control, &amount);
- if (amount != 0)
- DoScrollContent(pWindow, pData, amount, 0);
- }
-
- } // HActionProc
-
- #if GENERATINGCFM
- static RoutineDescriptor gHActionProcRD = BUILD_ROUTINE_DESCRIPTOR(uppControlActionProcInfo, HActionProc);
- static ControlActionUPP gHActionProc = &gHActionProcRD;
- #else
- static ControlActionUPP gHActionProc = HActionProc;
- #endif
-
- // --------------------------------------------------------------------------------------------------------------
- // END SCROLL ACTION PROCS
- // --------------------------------------------------------------------------------------------------------------
-
- #pragma segment Main
-
- static OSErr DoContentClick(WindowRef pWindow)
- {
- OSErr anErr = noErr;
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
-
- if ( pData )
- {
- SetPort((GrafPtr) GetWindowPort(pWindow));
-
- if (pData->pContentClick)
- {
- // let the object handle the click if it wishes to
- anErr = (*(pData->pContentClick)) (pWindow, pData, &gEvent);
- }
-
- if (anErr == noErr)
- {
- ControlRef theControl;
- short part;
-
- GlobalToLocal(&gEvent.where);
- part = FindControl(gEvent.where, pWindow, &theControl);
- switch (part)
- {
- // do nothing for viewRect case
- case 0:
- break;
-
- // track the thumb, and then update all at once
- case kControlIndicatorPart:
- {
- short value = GetControlValue(theControl);
-
- part = TrackControl(theControl, gEvent.where, nil);
- if (part != 0)
- {
- // turn the value into a delta
- value -= GetControlValue(theControl);
-
- // if we actually moved
- if (value != 0)
- {
- if (theControl == pData->hScroll)
- DoScrollContent(pWindow, pData, value, 0);
- if (theControl == pData->vScroll)
- DoScrollContent(pWindow, pData, 0, value);
-
- }
- }
- }
- break;
-
- // track the control, and scroll as we go
- default:
- if (theControl)
- {
- if (theControl == pData->hScroll)
- part = TrackControl(theControl, gEvent.where, gHActionProc);
- if (theControl == pData->vScroll)
- part = TrackControl(theControl, gEvent.where, gVActionProc);
- }
- break;
- }
- }
-
- }
-
-
- return anErr;
-
- } // DoContentClick
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr DoGrowWindow(WindowRef pWindow, EventRecord *pEvent)
- {
- OSErr anErr = noErr;
- WindowDataPtr pData = GetWindowInfo(pWindow);
- Rect tempRect;
- LongRect docRect;
- long growResult;
-
- if (pData)
- {
- GrafPtr pPort = (GrafPtr)GetWindowPort(pWindow);
-
- SetPort(pPort);
-
- RectToLongRect(&pData->contentRect, &docRect);
- if (pData->pGetDocumentRect)
- (*(pData->pGetDocumentRect)) (pWindow, pData, &docRect, true);
- if (pData->vScroll)
- docRect.right += 16;
- if (pData->hScroll)
- docRect.bottom += 16;
-
- if ( (pData->hasGrow) && (pData->hScroll == nil) && (pData->vScroll == nil) )
- {
- docRect.right += 16;
- docRect.bottom += 16;
- }
-
- // set up resize constraints
- tempRect.left = pData->minHSize;
- if (tempRect.left == 0)
- tempRect.left = kMinDocSize;
- tempRect.right = docRect.right - docRect.left;
- if (tempRect.right < tempRect.left)
- tempRect.right = tempRect.left;
- tempRect.top = pData->minVSize;
- if (tempRect.top == 0)
- tempRect.top = kMinDocSize;
- tempRect.bottom = docRect.bottom - docRect.top;
- if (tempRect.bottom < tempRect.top)
- tempRect.bottom = tempRect.top;
-
- growResult = GrowWindow(pWindow, pEvent->where, &tempRect);
- if ( growResult != 0 )
- {
- Rect oldRect;
- RgnHandle currentInval = NewRgn();
- Boolean needInvalidate;
-
- // save old content area
- oldRect = pData->contentRect;
-
- // save old pending update
- GetWindowUpdateRgn(pWindow, currentInval);
- OffsetRgn(currentInval, pPort->portBits.bounds.left, pPort->portBits.bounds.top);
-
- // grow window and recalc what is needed
- SizeWindow(pWindow, growResult & 0xFFFF, growResult >> 16, true);
- AdjustScrollBars(pWindow, true, true, &needInvalidate);
-
- if (needInvalidate)
- {
- InvalRect(&pData->contentRect);
- }
- else
- {
- // don't bother to redraw things that haven't changed
- SectRect(&oldRect, &pData->contentRect, &oldRect);
- ValidRect(&oldRect);
-
- // but, if a pending update was there, be sure to deal with that!
- InvalRgn(currentInval);
- }
-
- // if we have offset scrollbars, then force a redraw of them
- if (pData->hScrollOffset)
- {
- oldRect = GetWindowPort(pWindow)->portRect;
- oldRect.right = oldRect.left + pData->hScrollOffset;
- oldRect.top = oldRect.bottom - kScrollBarSize;
- InvalRect(&oldRect);
- }
- if (pData->vScrollOffset)
- {
- oldRect = GetWindowPort(pWindow)->portRect;
- oldRect.bottom = oldRect.top + pData->vScrollOffset;
- oldRect.left = oldRect.right - kScrollBarSize;
- InvalRect(&oldRect);
- }
-
- DisposeRgn(currentInval);
- }
-
- }
-
-
- return anErr;
-
- } // DoGrowWindow
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr DoZoomWindow(WindowRef pWindow, short zoomDir)
- {
- Rect *windRect, *zoomRect;
- Rect globalPortRect, theSect, dGDRect;
- GDHandle nthDevice, dominantGDevice;
- long sectArea, greatestArea;
- short hMax, vMax;
-
- // determine the max size of the window
- {
- WindowDataPtr pData = GetWindowInfo(pWindow);
- LongRect docRect;
-
- RectToLongRect(&pData->contentRect, &docRect);
- if (pData->pGetDocumentRect)
- (*(pData->pGetDocumentRect)) (pWindow, pData, &docRect, true);
- if (pData->vScroll)
- docRect.right += kScrollBarSize;
- if (pData->hScroll)
- docRect.bottom += kScrollBarSize;
-
- if ( (pData->hasGrow) && (pData->hScroll == nil) && (pData->vScroll == nil) )
- {
- docRect.right += kScrollBarSize;
- docRect.bottom += kScrollBarSize;
- }
-
- hMax = docRect.right - docRect.left;
- vMax = docRect.bottom - docRect.top;
- }
-
- SetPort((GrafPtr) GetWindowPort(pWindow));
- EraseRect(&GetWindowPort(pWindow)->portRect); // recommended for cosmetic reasons
-
- if (zoomDir == inZoomOut)
- {
-
- /*
- * ZoomWindow() is a good basic tool, but it doesn't do everything necessary to
- * implement a good human interface when zooming. In fact it's not even close for
- * more high-end hardware configurations. We must help it along by calculating an
- * appropriate window size and location any time a window zooms out.
- */
- {
- RgnHandle structRgn = NewRgn();
-
- GetWindowStructureRgn(pWindow, structRgn);
- windRect = &(**structRgn).rgnBBox;
- DisposeRgn(structRgn);
- }
- dominantGDevice = nil;
- if (gMachineInfo.theEnvirons.hasColorQD)
- {
-
- /*
- * Color QuickDraw implies the possibility of multiple monitors. This is where
- * zooming becomes more interesting. One should zoom onto the monitor containing
- * the greatest portion of the window. This requires walking the gDevice list.
- */
-
- nthDevice = GetDeviceList();
- greatestArea = 0;
- while (nthDevice != nil)
- {
- if (TestDeviceAttribute(nthDevice, screenDevice))
- {
- if (TestDeviceAttribute(nthDevice, screenActive))
- {
- SectRect(windRect, &(**nthDevice).gdRect, &theSect);
- sectArea = (long) RectWidth(theSect) * (long) RectHeight(theSect);
- if (sectArea > greatestArea)
- {
- greatestArea = sectArea; // save the greatest intersection
- dominantGDevice = nthDevice; // and which device it belongs to
- }
- }
- }
- nthDevice = GetNextDevice(nthDevice);
- }
- }
-
- /*
- * At this point, we know the dimensions of the window we're zooming, and we know
- * what screen we're going to put it on. To be more specific, however, we need a
- * rectangle which defines the maximum dimensions of the resized window's contents.
- * This rectangle accounts for the thickness of the window frame, the menu bar, and
- * one or two pixels around the edges for cosmetic compatibility with ZoomWindow().
- */
-
- if (dominantGDevice != nil)
- {
- dGDRect = (**dominantGDevice).gdRect;
- if (dominantGDevice == GetMainDevice()) // account for menu bar on main device
- dGDRect.top += GetMBarHeight();
- }
- else
- {
- dGDRect = qd.screenBits.bounds; // if no gDevice, use default monitor
- dGDRect.top += GetMBarHeight();
- }
-
- globalPortRect = GetWindowPort(pWindow)->portRect;
- LocalToGlobal(&TopLeft(globalPortRect)); // calculate the window's portRect
- LocalToGlobal(&BotRight(globalPortRect)); // in global coordinates
-
- // account for the window frame and inset it a few pixels
- dGDRect.left += 2 + globalPortRect.left - windRect->left;
- dGDRect.top += 2 + globalPortRect.top - windRect->top;
- dGDRect.right -= 1 + windRect->right - globalPortRect.right;
- dGDRect.bottom -= 1 + windRect->bottom - globalPortRect.bottom;
-
- /*
- * Now we know exactly what our limits are, and since there are input parameters
- * specifying the dimensions we'd like to see, we can move and resize the zoom
- * state rectangle for the best possible results. We have three goals in this:
- * 1. Display the window entirely visible on a single device.
- * 2. Resize the window to best represent the dimensions of the document itself.
- * 3. Move the window as short a distance as possible to achieve #1 and #2.
- */
-
- zoomRect = &(**(WStateDataHandle) ((WindowPeek) pWindow)->dataHandle).stdState;
-
- /*
- * Initially set the zoom rectangle to the size requested by the input parameters,
- * although not smaller than a minimum size. We do this without moving the origin.
- */
-
- zoomRect->right = (zoomRect->left = globalPortRect.left) +
- Max(hMax, kMinDocSize);
- zoomRect->bottom = (zoomRect->top = globalPortRect.top) +
- Max(vMax, kMinDocSize);
-
- // Shift the entire rectangle if necessary to bring its origin inside dGDRect.
- OffsetRect(zoomRect,
- Max(dGDRect.left - zoomRect->left, 0),
- Max(dGDRect.top - zoomRect->top, 0));
-
- /*
- * Shift the rectangle up and/or to the left if necessary to accomodate the view,
- * and if it is possible to do so. The rectangle may not be moved such that its
- * origin would fall outside of dGDRect.
- */
-
- OffsetRect(zoomRect,
- -Pin(zoomRect->right - dGDRect.right, 0, zoomRect->left - dGDRect.left),
- -Pin(zoomRect->bottom - dGDRect.bottom, 0, zoomRect->top - dGDRect.top));
-
- // Clip expansion to dGDRect, in case view is larger than dGDRect.
- zoomRect->right = Min(zoomRect->right, dGDRect.right);
- zoomRect->bottom = Min(zoomRect->bottom, dGDRect.bottom);
- }
-
- ZoomWindow(pWindow, zoomDir, pWindow == FrontWindow());
-
- AdjustScrollBars(pWindow, true, true, nil);
-
- InvalRect(&GetWindowPort(pWindow)->portRect);
-
- return noErr;
-
- } // DoZoomWindow
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- OSErr DoActivate(WindowRef pWindow, Boolean activating)
- {
-
- OSErr anErr = noErr;
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- SetPort((GrafPtr) GetWindowPort(pWindow));
-
- if ( pData )
- {
- if (pData->pActivateEvent)
- anErr = (*(pData->pActivateEvent)) (pWindow, pData, activating);
-
- if (anErr == noErr)
- {
- if (activating)
- {
- // Reshow all controls on activation
- if (pData->hScroll)
- ShowControl(pData->hScroll);
- if (pData->vScroll)
- ShowControl(pData->vScroll);
- }
- else
- {
- // Hide all controls on deactivation
- if (pData->hScroll)
- HideControl(pData->hScroll);
- if (pData->vScroll)
- HideControl(pData->vScroll);
- }
-
- if (pData->hasGrow)
- {
- Rect growIconRect;
-
- CalculateGrowIcon(pData, &growIconRect);
- InvalRect(&growIconRect);
- }
- }
- }
-
- AdjustMenus(pWindow, true, false);
-
- return anErr;
-
- } // DoActivate
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr DoStartupGX(void)
- {
- gxGraphicsError anErr = noErr;
-
- if (!gMachineInfo.haveStartedGX)
- {
- GXEnterGraphics();
- GXGetGraphicsError(&anErr);
- if ( (anErr == noErr) && (GXGetGraphicsClient() == nil) )
- anErr = out_of_memory;
- if (anErr == noErr)
- {
- anErr = GXInitPrinting();
- if (anErr != noErr)
- GXExitGraphics();
- }
-
- if (anErr != noErr)
- GXSetGraphicsClient(nil);
- }
-
- if (GXGetGraphicsClient() == nil)
- anErr = out_of_memory;
-
- if (anErr == noErr)
- gMachineInfo.haveStartedGX = true;
-
- return anErr;
-
- } // DoStartupGX
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- OSErr DoDefault(WindowDataPtr pData)
- {
- OSErr anErr = noErr;
-
- if (gMachineInfo.haveGX)
- {
- // start up GX, if needed
- anErr = DoStartupGX();
-
- if (anErr == noErr)
- {
-
- // default the job if we don't have it
- if (pData->hPrint == nil)
- {
- anErr = GXNewJob((gxJob*)&pData->hPrint);
- if (anErr == noErr)
- {
- GXInstallApplicationOverride(pData->hPrint, gxPrintingEventMsg, gPrintingEventMessage);
- GXInstallApplicationOverride(pData->hPrint, gxCompleteSpoolFileMsg, gCompleteSpoolFileMessage);
- }
- }
- }
- }
- else
- {
- PrOpen();
- anErr = PrError();
- if (anErr == noErr)
- {
- if (pData->hPrint == nil)
- {
- pData->hPrint = NewHandleClear(sizeof(TPrint));
- anErr = MemError();
- if (anErr == noErr)
- PrintDefault(pData->hPrint);
- }
-
- }
- PrClose();
- }
-
- return anErr;
-
- } // DoDefault
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static void SetupForPrintDialogs(gxEditMenuRecord * pEdit)
- {
- MenuHandle menu;
- short menuID, itemID;
-
- CommandToIDs(cCut, &pEdit->editMenuID, &pEdit->cutItem);
- CommandToIDs(cCopy, &pEdit->editMenuID, &pEdit->copyItem);
- CommandToIDs(cPaste, &pEdit->editMenuID, &pEdit->pasteItem);
- CommandToIDs(cClear, &pEdit->editMenuID, &pEdit->clearItem);
- CommandToIDs(cUndo, &pEdit->editMenuID, &pEdit->undoItem);
-
- // diable everything we don't want to deal with
- for (menuID = mApple; menuID <= mLastMenu; ++menuID)
- {
- menu = GetMenuHandle(menuID);
-
- if (menu)
- {
- switch (menuID)
- {
- case mApple:
- CommandToIDs(cAbout, &menuID, &itemID);
- DisableItem(menu, itemID);
- break;
-
- case mEdit:
- CommandToIDs(cSelectAll, &menuID, &itemID);
- DisableItem(menu, itemID);
- CommandToIDs(cShowClipboard, &menuID, &itemID);
- DisableItem(menu, itemID);
- break;
-
- default:
- DisableItem(menu, 0);
- break;
- }
- }
- }
-
- // Disable the current indicator because the dialogs are moveable modal
- HiliteMenu(0);
-
- } // SetupForPrintDialogs
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- OSErr DoPageSetup(WindowRef pWindow)
- {
- OSErr anErr = noErr;
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- anErr = DoDefault(pData);
- nrequire(anErr, DoDefault);
-
- if (gMachineInfo.haveGX)
- {
- gxEditMenuRecord theEdit;
-
- SetupForPrintDialogs(&theEdit);
-
- GXJobDefaultFormatDialog(pData->hPrint, &theEdit);
- anErr = GXGetJobError(pData->hPrint);
-
- AdjustMenus(pWindow, true, true);
- }
- else
- {
- PrOpen();
- anErr = PrError();
- if (anErr == noErr)
- {
- SetCursor(&qd.arrow);
- PrStlDialog(pData->hPrint);
- }
- PrClose();
- }
-
- // FALL THROUGH EXCEPTION HANDLING
- DoDefault:
- return anErr;
-
- } // DoPageSetup
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr DoPrintSetup(WindowRef pWindow, StringPtr pPrinterName)
- {
- OSErr anErr = noErr;
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- anErr = DoDefault(pData);
- nrequire(anErr, DoDefault);
-
- if (gMachineInfo.haveGX)
- {
- gxEditMenuRecord theEdit;
- gxDialogResult result;
-
- // toss any previous errors that might be around
- (void)GXGetJobError(pData->hPrint);
-
- if ( (pPrinterName) && (pPrinterName[0] != 0) )
- GXSelectJobOutputPrinter(pData->hPrint, pPrinterName);
- else
- {
- SetupForPrintDialogs(&theEdit);
- result = GXJobPrintDialog(pData->hPrint, &theEdit);
- AdjustMenus(pWindow, true, true);
- }
- if (anErr == noErr)
- {
- anErr = GXGetJobError(pData->hPrint);
- if ( (anErr == noErr) && (result == gxCancelSelected) )
- anErr = eUserCanceled;
- }
- }
- else
- {
- PrOpen();
- anErr = PrError();
- if (anErr == noErr)
- {
- SetCursor(&qd.arrow);
- if (PrJobDialog(pData->hPrint) == false)
- anErr = eUserCanceled;
- }
-
- PrClose();
- }
-
- // FALL THROUGH EXCEPTION HANDLING
- DoDefault:
- return anErr;
-
- } // DoPrintSetup
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr DoPrint(WindowRef pWindow, void * hPrint, Boolean oneCopy)
- {
- gxGraphicsError anErr = noErr;
- WindowDataPtr pData = GetWindowInfo(pWindow);
- Boolean didAllocate = false;
-
- // use a watch cursor while printing
- SetWatchCursor();
-
- if (gMachineInfo.haveGX)
- {
- // startup GX, if needed
- anErr = DoStartupGX();
-
- if ( (anErr == noErr) && (hPrint == nil) )
- {
- anErr = GXNewJob((gxJob*)&hPrint);
- if (anErr == noErr)
- {
- GXInstallApplicationOverride(hPrint, gxPrintingEventMsg, gPrintingEventMessage);
- GXInstallApplicationOverride(hPrint, gxCompleteSpoolFileMsg, gCompleteSpoolFileMessage);
- didAllocate = true;
- }
- }
-
- if (anErr == noErr)
- {
- Str255 docName;
-
- if (oneCopy)
- {
- gxCopiesInfo theCopies;
-
- theCopies.copies = 1;
- AddCollectionItem(GXGetJobCollection(hPrint), gxCopiesTag, gxPrintingTagID, sizeof(theCopies), &theCopies);
- }
-
- GXSetJobRefCon(hPrint, pData);
-
- GetWTitle(pWindow, docName);
- GXStartJob(hPrint, docName, 0);
- anErr = GXGetJobError(hPrint);
- if (anErr == noErr)
- {
- long first, last, pageIndex;
- Rect pageRect;
- CGrafPort thePort;
-
- // determine size of page, and number of pages
- {
- gxRectangle pageSize;
- GXGetFormatDimensions(GXGetJobFormat(hPrint, 1), &pageSize, nil);
- pageRect.top = pageSize.top >> 16;
- pageRect.left = pageSize.left >> 16;
- pageRect.bottom = pageSize.bottom >> 16;
- pageRect.right = pageSize.right >> 16;
- }
- GXGetJobPageRange(hPrint, &first, &last);
- anErr = GXGetJobError(hPrint);
- if (first < 1)
- first = 1;
- if (last < first)
- last = first;
-
- if (anErr == noErr)
- {
- // make a port to perform translation in
- OpenCPort(&thePort);
-
- for (pageIndex = first; pageIndex <= last; ++pageIndex)
- {
- SetPort((GrafPtr) &thePort);
-
- if (pData->documentOutputsGX)
- anErr = (*(pData->pPrintPage)) (pWindow, pData, &pageRect, &pageIndex);
- else
- {
- Point patStretch = {1,1};
- gxTranslationOption options = gxOptimizedTranslation;
- CatchRefCon theRefCon;
-
- if (GXGetPrinterDriverType(GXGetJobPrinter(hPrint)) == 'post')
- options += gxPostScriptTargetTranslation;
- else
- options += gxRasterTargetTranslation;
-
- theRefCon.theJob = hPrint;
- theRefCon.doLayout = (pData->originalFileType == 'TEXT');
- theRefCon.thePage = GXNewShape(gxPictureType);
- theRefCon.thePageRectangle.top = ff(pageRect.top);
- theRefCon.thePageRectangle.left = ff(pageRect.left);
- theRefCon.thePageRectangle.bottom = ff(pageRect.bottom);
- theRefCon.thePageRectangle.right = ff(pageRect.right);
-
- GXInstallQDTranslator(
- qd.thePort,
- options,
- &pageRect,
- &pageRect,
- patStretch,
- gSimpleCatchShape,
- &theRefCon);
- GXGetGraphicsError(&anErr);
-
- if (anErr == noErr)
- {
- long whichPage = pageIndex;
-
- anErr = (*(pData->pPrintPage)) (pWindow, pData, &pageRect, &whichPage);
- GXRemoveQDTranslator(qd.thePort, nil);
-
- GXPrintPage(hPrint, pageIndex, nil, theRefCon.thePage);
- anErr = GXGetJobError(hPrint);
- pageIndex = whichPage;
- }
-
- GXDisposeShape(theRefCon.thePage);
- }
-
- if (anErr == noErr)
- GXGetGraphicsError(&anErr);
-
- // bail when we are told to stop
- if ( (pageIndex == -1) || (anErr != noErr) )
- break;
- }
-
- // all done with our temp port and job
- CloseCPort(&thePort);
- }
-
- GXFinishJob(hPrint);
- if (anErr == noErr) anErr = GXGetJobError(hPrint);
- }
-
- }
-
- if (didAllocate)
- GXDisposeJob(hPrint);
-
- // restore those menus!
- AdjustMenus(pWindow, true, true);
-
- }
- else
- {
- TPPrPort printingPort;
-
- PrOpen();
- anErr = PrError();
- if (anErr == noErr)
- {
- if (hPrint == nil)
- {
- hPrint = NewHandleClear(sizeof(TPrint));
- anErr = MemError();
- if (anErr == noErr)
- {
- PrintDefault(hPrint);
- didAllocate = true;
- }
- }
-
- if (anErr == noErr)
- {
- short firstPage, lastPage;
-
- // be sure to get the page range BEFORE calling PrValidate(),
- // which blows it away for many drivers.
- firstPage = (**(THPrint)hPrint).prJob.iFstPage;
- lastPage = (**(THPrint)hPrint).prJob.iLstPage;
-
- // make sure the print record is cool to use
- PrValidate(hPrint);
-
- // then clear out the job itself -- some drivers don't
- // do this from within PrValidate(). We want the job
- // clear in case the driver bases background behavior
- // from this range (and many do).
- (**(THPrint)hPrint).prJob.iFstPage = 1;
- (**(THPrint)hPrint).prJob.iLstPage = 9999;
-
- if (oneCopy)
- (** ((THPrint)hPrint)).prJob.iCopies = 1;
-
- // start printing, and then loop over the pages
- printingPort = PrOpenDoc(hPrint, nil, nil);
- anErr = PrError();
- if (anErr == noErr)
- {
- long pageIndex;
- Rect pageRect;
-
- SetPort((GrafPtr) printingPort);
-
- pageRect = (**(THPrint)hPrint).prInfo.rPage;
- if (firstPage < 1)
- firstPage = 1;
- if (lastPage < firstPage)
- lastPage = firstPage;
- for (pageIndex = firstPage; pageIndex <= lastPage; ++pageIndex)
- {
- PrOpenPage(printingPort, nil);
- anErr = PrError();
- if (anErr == noErr)
- anErr = (*(pData->pPrintPage)) (pWindow, pData, &pageRect, &pageIndex);
-
- PrClosePage(printingPort);
- if (anErr == noErr)
- anErr = PrError();
- if ( (anErr != noErr) || (pageIndex == -1) )
- break;
- }
- }
-
- // Finish up printing of the document
- PrCloseDoc(printingPort);
- if (anErr == noErr)
- anErr = PrError();
- if ( (anErr == noErr) && ((**(THPrint)hPrint).prJob.bJDocLoop == bSpoolLoop) )
- {
- TPrStatus theStatus;
-
- PrPicFile(hPrint, nil, nil, nil, &theStatus);
- anErr = PrError();
- }
- }
-
- if (didAllocate)
- DisposeHandle((Handle) hPrint);
-
- }
- PrClose();
- }
-
-
- // restore cursor
- SetCursor(&qd.arrow);
-
- return anErr;
-
- } // DoPrint
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- OSErr DoCommand(WindowRef pWindow, short commandID, long menuResult)
- {
- OSErr anErr = noErr;
- WindowDataPtr pData = nil;
-
- if (pWindow)
- {
- pData = (WindowDataPtr) GetWindowInfo(pWindow);
-
- if ( (pData) && (pData->pCommand) )
- anErr = (*(pData->pCommand)) (pWindow, pData, commandID, menuResult);
- }
-
- if (anErr == noErr)
- {
- // default command handling
- switch (commandID)
- {
- // About box command
- case cAbout:
- if (!BringToFrontIfExists(kAboutWindow))
- anErr = MakeNewWindow(kAboutWindow, nil, '????', nil);
- break;
-
- case cDeskAccessory:
- {
- Str255 tempString;
-
- GetMenuItemText(GetMenuHandle(menuResult>>16), menuResult & 0xFFFF, tempString);
- OpenDeskAcc(tempString);
- }
- break;
-
- // New window command
- case cNew:
- anErr = MakeNewWindow(kTextWindow, nil, 'TEXT', nil);
- break;
-
- // Open window command
- case cOpen:
- anErr = DoOpenWindow();
- break;
-
- // Close window command
- case cClose:
- anErr = DoCloseWindow(pWindow);
- break;
-
- case cPageSetup:
- anErr = DoPageSetup(pWindow);
- break;
-
- case cPrint:
- anErr = DoPrintSetup(pWindow, nil);
- if (anErr == noErr)
- anErr = DoPrint(pWindow, pData->hPrint, false);
- break;
-
- case cPrintOneCopy:
- anErr = DoPrint(pWindow, pData->hPrint, true);
- break;
-
- // get out of here command!
- case cQuit:
- gAllDone = true;
- break;
-
- // show/hide clipboard
- case cShowClipboard:
- if (!BringToFrontIfExists(kClipboardWindow))
- {
- anErr = MakeNewWindow(kClipboardWindow, nil, '????', nil);
- }
- else
- {
- pWindow = FrontWindow();
- anErr = DoCloseWindow(pWindow);
- }
- break;
-
- case cNextPage:
- gEvent.what = keyDown;
- gEvent.message = kPageDown << 8;
- gEvent.modifiers = 0;
- DoKeyEvent(pWindow, &gEvent, false);
- break;
-
- case cPreviousPage:
- gEvent.what = keyDown;
- gEvent.message = kPageUp << 8;
- gEvent.modifiers = 0;
- DoKeyEvent(pWindow, &gEvent, false);
- break;
-
- // Do nothing command
- case cNull:
- break;
-
- default:
- break;
- }
- }
-
- // don't report cancels
- if ( (anErr == iPrAbort) || (anErr == gxPrUserAbortErr) )
- anErr = noErr;
-
- // some errors map to other errors because they are basically the same
- // This way we can use the same string.
- if (anErr == out_of_memory)
- anErr = memFullErr;
-
- if ( (anErr != noErr) && (anErr != eActionAlreadyHandled) && (anErr != eUserCanceled) )
- {
- // some commands are so similar to other commands that we map their IDs
- // for the purposes of the error strings
- if (commandID == cSaveAs)
- commandID = cSave;
- if (commandID == cPrintOneCopy)
- commandID = cPrint;
-
- ConductErrorDialog(anErr, commandID, cancel);
- }
-
- // in any case, unhilite the menu selected after command processing is done
- HiliteMenu(0);
-
- return anErr;
-
- } // DoCommand
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr DoMenuCommand(WindowRef pWindow, long menuResult)
- {
- OSErr anErr = noErr;
- short commandID = cNull;
- short ** commandHandle;
- short menuID = menuResult >> 16;
-
- if (menuID == kHMHelpMenuID)
- {
- // close existing database (if any)
- if ((gAGRefNum != -1) && AGIsDatabaseOpen(gAGRefNum))
- {
- AGClose(&gAGRefNum);
- gAGRefNum = -1;
- }
-
- // and open the database we have found in the past
- AGOpen(&gAGSpec, 0, nil, &gAGRefNum);
- }
- else
- {
- if (menuID >= mFontSubMenusStart)
- {
- commandID = cSelectFontStyle;
- }
- else
- {
- // read in the resource that controls this menu
- {
- short oldResFile = CurResFile();
-
- UseResFile(gApplicationResFile);
- commandHandle = (short**) Get1Resource('MCMD', menuID);
- UseResFile(oldResFile);
- anErr = ResError();
- nrequire(anErr, FailedToLoadCommandTable);
- }
-
- if (commandHandle)
- {
- short item = menuResult & 0xFFFF;
- short * pCommands = *commandHandle;
-
- if (item <= pCommands[0])
- commandID = pCommands[item];
- else
- commandID = pCommands[pCommands[0]];
- }
- }
-
- anErr = DoCommand(pWindow, commandID, menuResult);
- }
-
- // FALL THROUGH EXCEPTION HANDLING
- FailedToLoadCommandTable:
-
- return anErr;
-
- } // DoMenuCommand
-
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static void DoKeyPageDown(WindowRef pWindow, WindowDataPtr pData, Boolean processPageControls)
- {
-
- if (GetControlValue(pData->vScroll) < GetControlMaximum(pData->vScroll))
- VActionProc(pData->vScroll, kControlPageDownPart);
- else
- {
- if ( (processPageControls) && (IsCommandEnabled(cNextPage)) )
- {
- short amount;
-
- if (DoCommand(pWindow, cNextPage, 0) == eActionAlreadyHandled)
- {
- amount = GetControlValue(pData->vScroll);
- SetControlAndClipAmount(pData->vScroll, &amount);
- if (amount != 0)
- DoScrollContent(pWindow, pData, 0, amount);
- }
-
- AdjustMenus(pWindow, true, false);
- }
- }
-
- } // DoKeyPageDown
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static void DoKeyPageUp(WindowRef pWindow, WindowDataPtr pData, Boolean processPageControls)
- {
- if (GetControlValue(pData->vScroll) > GetControlMinimum(pData->vScroll))
- VActionProc(pData->vScroll, kControlPageUpPart);
- else
- {
- if ( (processPageControls) && (IsCommandEnabled(cPreviousPage)) )
- {
- short amount;
-
- if (DoCommand(pWindow, cPreviousPage, 0) == eActionAlreadyHandled)
- {
- amount = -(GetControlMaximum(pData->vScroll)-GetControlValue(pData->vScroll));
- SetControlAndClipAmount(pData->vScroll, &amount);
- if (amount != 0)
- DoScrollContent(pWindow, pData, 0, amount);
- }
-
- AdjustMenus(pWindow, true, false);
- }
- }
-
- } // DoKeyPageUp
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- OSErr DoKeyEvent(WindowRef pWindow, EventRecord * pEvent, Boolean processPageControls)
- {
- OSErr anErr = noErr;
- WindowDataPtr pData = nil;
- Boolean passToObject = false;
- Boolean isMotionKey = false;
- long menuResult = 0;
-
- char keyCode = (pEvent->message >> 8) & charCodeMask;
-
- if ( pEvent->modifiers & cmdKey ) /* Command key down */
- {
- AdjustMenus(pWindow, true, false);
- menuResult = MenuKey(pEvent->message & charCodeMask);
- DoMenuCommand(pWindow, menuResult);
- pWindow = FrontWindow();
- }
-
- if (menuResult == 0)
- {
- if (pWindow)
- {
- pData = (WindowDataPtr)GetWindowInfo(pWindow);
- if ( (pData) && (pData->pKeyEvent) )
- passToObject = true;
- SetPort((GrafPtr) GetWindowPort(pWindow));
- }
-
- if (pData)
- {
- switch (keyCode)
- {
- case kHome: // top of file
- isMotionKey = true;
- if (pData->vScroll)
- {
- short amount;
-
- if ( (processPageControls) && (IsCommandEnabled(cGotoPage)) )
- DoCommand(pWindow, cGotoPage, cGotoFirst);
-
- amount = GetControlValue(pData->vScroll);
- SetControlAndClipAmount(pData->vScroll, &amount);
- if (amount != 0)
- DoScrollContent(pWindow, pData, 0, amount);
- passToObject = false;
- }
- break;
-
- case kEnd: // end of file
- isMotionKey = true;
- if (pData->vScroll)
- {
- short amount;
-
- if ( (processPageControls) && (IsCommandEnabled(cGotoPage)) )
- DoCommand(pWindow, cGotoPage, cGotoLast);
-
- amount = -(GetControlMaximum(pData->vScroll)-GetControlValue(pData->vScroll));
- SetControlAndClipAmount(pData->vScroll, &amount);
- if (amount != 0)
- DoScrollContent(pWindow, pData, 0, amount);
- passToObject = false;
- }
- break;
-
- case kPageUp: // scroll bar page up
- isMotionKey = true;
- if (pData->vScroll)
- {
- DoKeyPageUp(pWindow, pData, processPageControls);
- passToObject = false;
- }
- break;
-
- case kPageDown: // scroll bar page down
- isMotionKey = true;
- if (pData->vScroll)
- {
- DoKeyPageDown(pWindow, pData, processPageControls);
- passToObject = false;
- }
- break;
-
- case kUpArrow: // scroll bar up arrow
- isMotionKey = true;
- if ( (pData->vScroll) && (!pData->pKeyEvent) )
- {
- if ( pEvent->modifiers & cmdKey ) /* Command key down */
- DoKeyPageUp(pWindow, pData, processPageControls);
- else
- VActionProc(pData->vScroll, kControlUpButtonPart);
- passToObject = false;
- }
- break;
-
- case kDownArrow: // scroll bar down arrow
- isMotionKey = true;
- if ( (pData->vScroll) && (!pData->pKeyEvent) )
- {
- if ( pEvent->modifiers & cmdKey ) /* Command key down */
- DoKeyPageDown(pWindow, pData, processPageControls);
- else
- VActionProc(pData->vScroll, kControlDownButtonPart);
- passToObject = false;
- }
- break;
-
- case kLeftArrow: // scroll bar left arrow
- isMotionKey = true;
- if ( (pData->hScroll) && (!pData->pKeyEvent) )
- {
- if ( pEvent->modifiers & cmdKey ) /* Command key down */
- HActionProc(pData->hScroll, kControlPageUpPart);
- else
- HActionProc(pData->hScroll, kControlUpButtonPart);
- passToObject = false;
- }
- break;
-
- case kRightArrow: // scroll bar right arrow
- isMotionKey = true;
- if ( (pData->hScroll) && (!pData->pKeyEvent) )
- {
- if ( pEvent->modifiers & cmdKey ) /* Command key down */
- HActionProc(pData->hScroll, kControlPageDownPart);
- else
- HActionProc(pData->hScroll, kControlDownButtonPart);
- passToObject = false;
- }
- break;
- }
-
- if (passToObject)
- anErr = (*(pData->pKeyEvent)) (pWindow, pData, pEvent, isMotionKey);
- else
- {
- if ( (pData->documentAcceptsText == false) && !( pEvent->modifiers & cmdKey ) && !(isMotionKey) )
- anErr = eDocumentNotModifiable;
- }
- }
-
- if ( (anErr != noErr) && (anErr != eActionAlreadyHandled) )
- ConductErrorDialog(anErr, cTypingCommand, ok);
-
- } // (menuResult == 0)
-
-
- return anErr;
-
- } // DoKeyEvent
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr DoAdjustCursor(WindowRef pWindow)
- {
- OSErr anErr = noErr;
- Point mouse;
- Boolean didAdjust = false;
-
- if (pWindow)
- {
- // not one of our windows? don't do anything
- if (GetWindowKind(pWindow) != userKind)
- didAdjust = true;
-
- SetPort((GrafPtr) GetWindowPort(pWindow));
-
- if ( (!didAdjust) && (gMachineInfo.haveTSM) )
- {
- GetMouse(&mouse);
- LocalToGlobal(&mouse);
- if (SetTSMCursor(mouse))
- didAdjust = true;
- }
-
- if (!didAdjust)
- {
- WindowDataPtr pData = GetWindowInfo(pWindow);
- RgnHandle content = NewRgn();
- Point globalMouse;
-
- GetMouse(&mouse);
- globalMouse = mouse;
- LocalToGlobal(&globalMouse);
-
- GetWindowContentRgn(pWindow, content);
- if ((pData) && (PtInRgn(globalMouse, content)) && (PtInRect(mouse, &pData->contentRect)))
- {
- Rect tempRect;
-
- tempRect = pData->contentRect;
- LocalToGlobal(&TopLeft(tempRect));
- LocalToGlobal(&BotRight(tempRect));
-
- if (pData->pAdjustCursor)
- anErr = (*(pData->pAdjustCursor)) (pWindow, pData, &mouse, &tempRect);
-
- RectRgn(gCursorRgn, &tempRect);
- }
- DisposeRgn(content);
- }
- else
- anErr = eActionAlreadyHandled;
- }
-
- // nobody set the cursor, we do it ourselves
- if (anErr != eActionAlreadyHandled)
- SetCursor(&qd.arrow);
-
- return anErr;
-
- } // DoAdjustCursor
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static long DetermineWaitTime(WindowRef pWindow)
- {
- long waitTime = kMaxWaitTime;
-
- while (pWindow)
- {
- long newWaitTime;
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- if ((pData) && (pData->pCalculateIdleTime))
- newWaitTime = (*(pData->pCalculateIdleTime)) (pWindow, pData);
- else
- newWaitTime = kMaxWaitTime;
-
- if (newWaitTime < waitTime)
- waitTime = newWaitTime;
-
- pWindow = GetNextWindow(pWindow);
- }
-
- return(waitTime);
-
- } // DetermineWaitTime
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- void HandleEvent(EventRecord * pEvent)
- {
- WindowRef pWindow = FrontWindow();
-
- switch (pEvent->what)
- {
- case kHighLevelEvent:
- AEProcessAppleEvent(pEvent);
- break;
-
- case osEvt:
- switch ((pEvent->message >> 24) & 0xFF) /* high byte of message */
- {
- case mouseMovedMessage:
- DoAdjustCursor(pWindow);
- break;
-
- case suspendResumeMessage: /* suspend/resume is also an activate/deactivate */
- gMachineInfo.amInBackground = (pEvent->message & 1) == 0;
- if (pWindow)
- DoActivate(pWindow, !gMachineInfo.amInBackground);
-
- // on resume, we must call GXUpdateJob for all active jobs in
- // order to get instant activation of extensions and to properly
- // handle potential shifting of driver names
- if ( (gMachineInfo.haveGX) && (!gMachineInfo.amInBackground) )
- {
- WindowRef walkWindows = pWindow;
-
- while (walkWindows)
- {
- WindowDataPtr pData = GetWindowInfo(walkWindows);
- if (pData)
- {
- gxJob theJob = pData->hPrint;
- if (theJob)
- {
- GXUpdateJob(theJob);
- }
- }
- walkWindows = GetNextWindow(walkWindows);
- }
- }
- break;
- }
- break;
-
- case activateEvt:
- pWindow = (WindowRef) pEvent->message;
- DoActivate(pWindow, (pEvent->modifiers & activeFlag) != 0);
- break;
-
- // disk inserted events must be handled, or uninitialized floppies
- // won't be recognized.
- case diskEvt:
- if ( HiWord(pEvent->message) != noErr )
- {
- Point where;
-
- SetPt(&where, 70, 50);
- ShowCursor();
- (void) DIBadMount(where, pEvent->message);
- }
- break;
-
- case mouseUp:
- break;
-
- case mouseDown:
- {
- short part = FindWindow(pEvent->where, &pWindow);
-
- switch ( part )
- {
- case inContent:
- if (pWindow != FrontWindow())
- SelectWindow(pWindow);
- else
- DoContentClick(pWindow);
- break;
-
- case inGoAway:
- if (TrackGoAway(pWindow, pEvent->where) )
- DoCommand(pWindow, cClose, 0);
- break;
-
- case inGrow:
- DoGrowWindow(pWindow, pEvent);
- break;
-
- case inZoomIn:
- case inZoomOut:
- if ( TrackBox(pWindow, pEvent->where, part) )
- DoZoomWindow(pWindow, part);
- break;
-
- case inDrag:
- {
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- if ( (pData) && (pData->dragWindowAligned) )
- DragAlignedWindow((WindowPtr) pWindow, pEvent->where, &qd.screenBits.bounds, nil, nil);
- else
- DragWindow(pWindow, pEvent->where, &qd.screenBits.bounds);
- }
- break;
-
- case inMenuBar: /* process a mouse menu command (if any) */
- {
- long menuResult;
-
- // force these threads to run to completion so the
- // contents of the menus are fully initialized
-
- if (gFontThread != kNoThreadID)
- {
- gDontYield = true;
- SetThreadState(gFontThread, kReadyThreadState, gFontThread);
- YieldToThread(gFontThread);
- gDontYield = false;
- }
- if (gAGThread != kNoThreadID)
- {
- gDontYield = true;
- SetThreadState(gAGThread, kReadyThreadState, gAGThread);
- YieldToThread(gAGThread);
- gDontYield = false;
- }
-
- pWindow = FrontWindow();
- AdjustMenus(pWindow, true, false);
- menuResult = MenuSelect(pEvent->where);
- if ( (gMachineInfo.haveTSM) && (TSMMenuSelect(menuResult)) )
- HiliteMenu(0);
- else
- DoMenuCommand(pWindow, menuResult);
- }
- break;
-
- case inSysWindow: /* let the system handle the mouseDown */
- SystemClick(pEvent, pWindow);
- break;
-
- } // switch(part)
- }
- break;
-
- case keyDown:
- case autoKey: /* check for menukey equivalents */
- DoKeyEvent(pWindow, pEvent, true);
- break;
-
- case updateEvt:
- pWindow = (WindowRef) pEvent->message;
- DoUpdateWindow(pWindow);
- break;
-
- } // switch (pEvent->what)
-
- } // HandleEvent
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr DoEventLoop(void)
- {
- OSErr anErr = noErr;
- Boolean gotEvent;
- Boolean trueGotEvent;
- WindowRef pWindow;
-
- do {
- pWindow = LMGetFirstWindow(); // walk all of our windows, even invisible ones
-
- DoAdjustCursor(pWindow);
- gotEvent = WaitNextEvent(everyEvent, &gEvent, DetermineWaitTime(pWindow), gCursorRgn);
- trueGotEvent = gotEvent;
-
- // WNE may close the window if it's owned by some silly extension.
- pWindow = LMGetFirstWindow();
-
- // let text services handle the event first if it wishes to do so
- if ( gMachineInfo.haveTSM )
- {
- ScriptCode keyboardScript;
- WindowRef theFront = FrontWindow();
-
- if (theFront)
- {
- SetPort((GrafPtr) GetWindowPort(theFront));
-
- keyboardScript = GetScriptManagerVariable(smKeyScript);
- if (FontToScript(qd.thePort->txFont) != keyboardScript)
- TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
- }
-
- if (TSMEvent(&gEvent))
- gotEvent = false;
- }
-
- // let all windows filter this event, and get time if they wish to
- while (pWindow)
- {
- WindowDataPtr pData = GetWindowInfo(pWindow);
- Boolean finishedEvent = false;
-
- // help manager for the front window
- if ( (pWindow == FrontWindow()) && (pData) && (!gMachineInfo.amInBackground) && (HMGetBalloons()) )
- {
- Point theMouse, tipLocation;
- short newBalloon = iNoBalloon;
- Rect tempRect;
-
- // find out where the mouse is
- SetPort((GrafPtr) GetWindowPort(pWindow));
- GetMouse(&theMouse);
-
- // and only do something if we are within the window itself
- if (PtInRect(theMouse, &GetWindowPort(pWindow)->portRect))
- {
- // is it in the vertical scroll bar?
- if (pData->vScroll)
- {
- tempRect = (**(pData->vScroll)).contrlRect;
- if (PtInRect(theMouse, &tempRect))
- {
- newBalloon = iHelpActiveScroll;
- if (GetControlMinimum(pData->vScroll) == GetControlMaximum(pData->vScroll))
- newBalloon = iHelpDimVertScroll;
- tipLocation.h = tempRect.right - kFromBottomTipOffset;
- tipLocation.v = tempRect.bottom - kFromBottomTipOffset;
- }
- }
-
- // is it in the horizontal scroll bar?
- if (pData->hScroll)
- {
- tempRect = (**(pData->hScroll)).contrlRect;
- if (PtInRect(theMouse, &tempRect))
- {
- newBalloon = iHelpActiveScroll;
- if (GetControlMinimum(pData->hScroll) == GetControlMaximum(pData->hScroll))
- newBalloon = iHelpDimHorizScroll;
- tipLocation.h = tempRect.right - kFromBottomTipOffset;
- tipLocation.v = tempRect.bottom - kFromBottomTipOffset;
- }
- }
-
- // is it in the grow box?
- if (pData->hasGrow)
- {
- CalculateGrowIcon(pData, &tempRect);
- if (PtInRect(theMouse, &tempRect))
- {
- newBalloon = iHelpGrowBox;
- tipLocation.h = tempRect.right - kFromBottomTipOffset;
- tipLocation.v = tempRect.bottom - kFromBottomTipOffset;
- }
- }
-
- // none of the above, must be the content
- if (newBalloon == iNoBalloon)
- {
- newBalloon = iHelpGenericContent;
- tempRect = pData->contentRect;
- if (pData->pGetBalloon)
- (*(pData->pGetBalloon)) (pWindow, pData, &theMouse, &newBalloon, &tempRect);
-
- tipLocation.h = tempRect.left + kFromTopTipOffset;
- tipLocation.v = tempRect.top + kFromTopTipOffset;
- }
-
- // show our new balloon, or remove the old one
- if (newBalloon != iNoBalloon)
- {
- if ( (gMachineInfo.lastBalloonIndex != newBalloon) || (!HMIsBalloon()) )
- {
- HMMessageRecord message;
-
- if (newBalloon != iDidTheBalloon)
- {
- message.hmmHelpType = khmmString;
- GetIndString(message.u.hmmString, kWindowHelpID, newBalloon);
- LocalToGlobal(&tipLocation);
- (void) HMShowBalloon(&message, tipLocation, nil, nil, 0, kDefaultBalloonVariant, 0);
- }
- gMachineInfo.lastBalloonIndex = newBalloon;
- }
- }
- else
- HMRemoveBalloon();
- }
-
-
- }
-
- // if we hit a window we know about, then do filtering
- if (pData)
- {
- if (pData->pFilterEvent)
- finishedEvent = (*(pData->pFilterEvent)) (pWindow, pData, &gEvent);
- }
-
- // if filtering indicates complete handling of event, then stop, and
- // do no regular processing.
- if (finishedEvent)
- {
- gotEvent = false;
- pWindow = nil;
- }
- else
- pWindow = GetNextWindow(pWindow);
- }
-
- if (gotEvent)
- HandleEvent(&gEvent);
-
- // close request?
- if (gAllDone)
- {
- pWindow = FrontWindow();
- while ((gAllDone) && (pWindow) )
- {
- WindowRef nextWindow = GetNextWindow(pWindow);
- OSErr closeError = DoCloseWindow(pWindow);
-
- // window didn't close? then don't quit
- if (pWindow == FrontWindow())
- gAllDone = false;
-
- // something bad happened, then don't quit
- if ( (closeError != noErr) /* && (closeError != eUserCanceled) */ )
- gAllDone = false;
-
- pWindow = nextWindow;
- }
- }
-
- // our threads are low-priority, so we only give time to them on idle
- if (gMachineInfo.haveThreads && !trueGotEvent && !gAllDone)
- YieldToAnyThread();
-
- } while (!gAllDone);
-
- return anErr;
-
- } // DoEventLoop
-
-
- // --------------------------------------------------------------------------------------------------------------
- // DRAG MANAGEMENT GLOBAL SUPPORT ROUTINES
- // --------------------------------------------------------------------------------------------------------------
-
- // Globals for our drag handlers
-
- Boolean gCanAccept; // if we can receive the item(s) being dragged
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Drag
-
- static pascal OSErr GlobalTrackingHandler(short message, WindowRef pWindow, void *handlerRefCon, DragReference theDragRef)
- {
- #pragma unused(handlerRefCon)
-
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- // Call the tracking handler associated with this type of window. Only allow messages referencing
- // a specific window to be passed to the handler.
-
- if (pData)
- {
- if (pData->pDragTracking)
- return ((*(pData->pDragTracking)) (pWindow, pData, theDragRef, message));
- }
-
- return noErr;
-
- } // GlobalTrackingHandler
-
- DragTrackingHandlerUPP gGlobalTrackingHandler;
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Drag
-
- static pascal OSErr GlobalReceiveHandler(WindowRef pWindow, void *handlerRefCon, DragReference theDragRef)
- {
- #pragma unused(handlerRefCon)
-
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- if (pData)
- {
- if (pData->pDragTracking)
- return ((*(pData->pDragReceive)) (pWindow, pData, theDragRef));
- }
-
- return noErr;
-
- } // GlobalReceiveHandler
-
- DragReceiveHandlerUPP gGlobalReceiveHandler;
-
- // --------------------------------------------------------------------------------------------------------------
- //
- // IsOnlyThisFlavor - Given a DragReference and a FlavorType, we iterate through the drag items to determine if
- // all are of flavor theType. If this is so, we return true. If any of the items are not
- // theType, we return false, indicating that we should not accept the drag.
- //
- #pragma segment Drag
-
- Boolean IsOnlyThisFlavor(DragReference theDragRef, FlavorType theType)
- {
- unsigned short items, index;
- FlavorFlags theFlags;
- ItemReference itemID;
- OSErr anErr = noErr;
-
- CountDragItems(theDragRef, &items);
-
- for(index = 1; index <= items; index++)
- {
- GetDragItemReferenceNumber(theDragRef, index, &itemID);
-
- anErr = GetFlavorFlags(theDragRef, itemID, theType, &theFlags);
- if(anErr == noErr)
- continue; // it's okay, this flavor is cool
-
- return false; // this item has at least one flavor we don't like
- }
-
- return true; // all flavors in this item were cool
-
- } // IsOnlyThisFlavor
-
- // --------------------------------------------------------------------------------------------------------------
- //
- // IsDropInFinderTrash - Returns true if the given dropLocation AEDesc is a descriptor of the Finder's Trash.
- //
- #pragma segment Drag
-
- Boolean IsDropInFinderTrash(AEDesc *dropLocation)
- {
- OSErr result;
- AEDesc dropSpec;
- FSSpec *theSpec;
- CInfoPBRec thePB;
- short trashVRefNum;
- long trashDirID;
-
- // Coerce the dropLocation descriptor into an FSSpec. If there's no dropLocation or
- // it can't be coerced into an FSSpec, then it couldn't have been the Trash.
-
- if ((dropLocation->descriptorType != typeNull) &&
- (AECoerceDesc(dropLocation, typeFSS, &dropSpec) == noErr))
- {
- unsigned char flags = HGetState(dropSpec.dataHandle);
-
- HLock(dropSpec.dataHandle);
- theSpec = (FSSpec *) *dropSpec.dataHandle;
-
- // Get the directory ID of the given dropLocation object.
-
- thePB.dirInfo.ioCompletion = 0L;
- thePB.dirInfo.ioNamePtr = (StringPtr) &theSpec->name;
- thePB.dirInfo.ioVRefNum = theSpec->vRefNum;
- thePB.dirInfo.ioFDirIndex = 0;
- thePB.dirInfo.ioDrDirID = theSpec->parID;
-
- result = PBGetCatInfoSync(&thePB);
-
- HSetState(dropSpec.dataHandle, flags);
- AEDisposeDesc(&dropSpec);
-
- if (result != noErr)
- return false;
-
- // If the result is not a directory, it must not be the Trash.
-
- if (!(thePB.dirInfo.ioFlAttrib & (1 << 4)))
- return false;
-
- // Get information about the Trash folder.
-
- FindFolder(theSpec->vRefNum, kTrashFolderType, kCreateFolder, &trashVRefNum, &trashDirID);
-
- // If the directory ID of the dropLocation object is the same as the directory ID
- // returned by FindFolder, then the drop must have occurred into the Trash.
-
- if (thePB.dirInfo.ioDrDirID == trashDirID)
- return true;
- }
-
- return false;
-
- } // IsDropInFinderTrash
-
- // --------------------------------------------------------------------------------------------------------------
- // APPLE EVENT SUPPORT ROUTINES
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static OSErr MissingParameterCheck(
- AppleEvent *inputEvent)
- /*
- This routine checks an input AppleEvent for the missing keyword.
- If the missing keyword is found, that means that some required
- parameters were missing (ie, an error).
-
- However, if the missing keyword isn't found, that means that we aren't missing
- any required parameters (that is to say, all REQUIRED parameters were supplied
- by the person who created the event).
-
- SOME DAY, THE ABOVE COMMENT WILL MAKE SENSE TO YOU. IT STILL DOESN'T
- TO ME AND I WAS THE ONE WHO WROTE IT.
- */
- {
- OSErr anErr;
- AEKeyword missingKeyword;
- DescType ignoredActualType;
- Size ignoredActualSize;
-
- anErr = AEGetAttributePtr(
- inputEvent,
- keyMissedKeywordAttr,
- typeWildCard,
- &ignoredActualType,
- (Ptr) &missingKeyword,
- sizeof(AEKeyword),
- &ignoredActualSize);
-
- if (anErr == noErr)
- anErr = errAEParamMissed;
- else
- if (anErr == errAEDescNotFound)
- anErr = noErr;
-
- return anErr;
-
- } // MissingParameterCheck
-
- // --------------------------------------------------------------------------------------------------------------
- // Globals for our handlers
- Boolean gQuitAfterPrint = true;
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static pascal OSErr DoOpenApp(
- AppleEvent *inputEvent,
- AppleEvent *outputEvent,
- long handlerRefCon)
- {
- #pragma unused (outputEvent, handlerRefCon)
-
- DoCommand(nil, cNew, 0);
- gQuitAfterPrint = false;
-
- // so that the initial document opens more quickly, we don't start
- // the threads until we get an OpenApp or OpenDocument AppleEvent
- if (gStarterThread != kNoThreadID)
- SetThreadState(gStarterThread, kReadyThreadState, gStarterThread);
-
- return(MissingParameterCheck(inputEvent));
-
- } // DoAppOpen
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static pascal OSErr DoQuitApp(
- AppleEvent *inputEvent,
- AppleEvent *outputEvent,
- long handlerRefCon)
- {
- #pragma unused (outputEvent, handlerRefCon)
-
- DoCommand(nil, cQuit, 0);
-
- return(MissingParameterCheck(inputEvent));
-
- } // DoQuitApp
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static pascal OSErr DoOpenOrPrint(
- AppleEvent *inputEvent,
- StringPtr pPrinterName) // nil == 0, zero length == print to default, other == printer name
- {
-
- OSErr anErr, anErr2;
- AEDescList docList; // list of docs passed in
- long index, itemsInList;
- void* hPrint;
- Boolean wasAlreadyOpen;
-
- anErr = AEGetParamDesc( inputEvent, keyDirectObject, typeAEList, &docList);
- nrequire(anErr, GetFileList);
-
- anErr = AECountItems( &docList, &itemsInList); // how many files passed in
- nrequire(anErr, CountDocs);
- for (index = 1; index <= itemsInList; index++) // handle each file passed in
- {
- AEKeyword keywd;
- DescType returnedType;
- Size actualSize;
- FSSpec theFSS;
-
- anErr = AEGetNthPtr( &docList, index, typeFSS, &keywd, &returnedType, // get file's info
- (Ptr)(&theFSS), sizeof(theFSS), &actualSize);
- nrequire(anErr, AEGetNthPtr);
-
- {
- FInfo theFileInfo;
-
- anErr = FSpGetFInfo(&theFSS, &theFileInfo);
- if (anErr == noErr)
- anErr = DetermineWindowTypeOrOpen(&theFSS, theFileInfo.fdType, nil, nil, &wasAlreadyOpen);
-
- if (anErr == eDocumentWrongKind)
- {
- if (pPrinterName)
- ConductErrorDialog(anErr, cPrint, cancel);
- else
- ConductErrorDialog(anErr, cOpen, cancel);
-
- anErr = noErr;
- break;
- }
-
- nrequire(anErr, DetermineWindowTypeOrOpen);
- }
-
- if (pPrinterName)
- {
- WindowRef pWindow = FrontWindow();
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- if (pData->pPrintPage)
- {
- if (index == 1)
- {
- anErr = DoPrintSetup(pWindow, pPrinterName);
- if (anErr == noErr)
- hPrint = pData->hPrint;
- }
-
- if (anErr == noErr)
- anErr = DoPrint(pWindow, hPrint, false);
-
- if (index != itemsInList)
- pData->hPrint = nil;
- }
-
- if (!wasAlreadyOpen)
- DoCloseWindow(pWindow);
-
- if (anErr != noErr)
- break;
- }
- }
-
- // finally, make sure we didn't miss any parameters
- anErr2 = MissingParameterCheck(inputEvent);
- if (anErr == noErr)
- anErr = anErr2;
-
- // FALL THROUGH EXCEPTION HANDLING
- DetermineWindowTypeOrOpen:
- AEGetNthPtr:
- CountDocs:
- // done with doc list
- (void) AEDisposeDesc( &docList);
-
- GetFileList:
-
- // don't report cancels from prints
- if (pPrinterName)
- {
- if ( (anErr == iPrAbort) || (anErr == gxPrUserAbortErr) )
- anErr = noErr;
- }
-
- if ( (anErr != noErr) && (anErr != eActionAlreadyHandled) && (anErr != eUserCanceled) )
- {
- if (pPrinterName)
- ConductErrorDialog(anErr, cPrint, cancel);
- else
- ConductErrorDialog(anErr, cOpen, cancel);
- }
-
- return anErr;
-
- } // DoOpenOrPrint
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static pascal OSErr DoOpenDocument(
- AppleEvent *inputEvent,
- AppleEvent *outputEvent,
- long handlerRefCon)
- {
- #pragma unused (outputEvent, handlerRefCon)
-
- OSErr anErr;
-
- if (IsCommandEnabled(cOpen))
- {
- gQuitAfterPrint = false;
- anErr = DoOpenOrPrint(inputEvent, nil);
- }
- else
- {
- anErr = errAEEventNotHandled;
- ConductErrorDialog(anErr, cOpen, cancel);
- }
-
- // so that the initial document opens more quickly, we don't start
- // the threads until we get an OpenApp or OpenDocument AppleEvent
- if (gStarterThread != kNoThreadID)
- SetThreadState(gStarterThread, kReadyThreadState, gStarterThread);
-
- return anErr;
-
- } // DoOpenDocument
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static pascal OSErr DoPrintDocument(
- AppleEvent *inputEvent,
- AppleEvent *outputEvent,
- long handlerRefCon)
- {
- #pragma unused (outputEvent, handlerRefCon)
- OSErr anErr;
- FSSpec printerFSS;
- AEDescList dtpList; // list of docs passed in
-
- if (IsCommandEnabled(cOpen))
- {
- // try to find out if this doc was dropped onto a printer
- anErr = AEGetAttributeDesc( inputEvent, keyOptionalKeywordAttr, typeAEList, &dtpList);
-
- if (anErr == noErr) // doc dragged to dtp?
- {
- AEKeyword keywd;
- DescType returnedType;
- Size actualSize;
-
- anErr = AEGetNthPtr( &dtpList, 1, typeFSS, &keywd, &returnedType, // get dtp info
- (Ptr)(&printerFSS), sizeof(printerFSS), &actualSize);
- }
-
- // if it wasn't, that's not an error, just print normally
- if (anErr != noErr)
- {
- printerFSS.name[0] = 0;
- anErr = noErr;
- }
-
- anErr = DoOpenOrPrint(inputEvent, &printerFSS.name[0]);
-
- // if we are opened just for printing -- quit afterwards
- if (gQuitAfterPrint)
- DoCommand(nil, cQuit, 0);
- }
- else
- {
- anErr = errAEEventNotHandled;
- ConductErrorDialog(anErr, cPrint, cancel);
- }
-
- return anErr;
-
- } // DoPrintDocument
-
- #if GENERATINGCFM
- static RoutineDescriptor gDoOpenAppRD = BUILD_ROUTINE_DESCRIPTOR(uppAEEventHandlerProcInfo, DoOpenApp);
- static AEEventHandlerUPP gDoOpenApp = &gDoOpenAppRD;
-
- static RoutineDescriptor gDoQuitAppRD = BUILD_ROUTINE_DESCRIPTOR(uppAEEventHandlerProcInfo, DoQuitApp);
- static AEEventHandlerUPP gDoQuitApp = &gDoQuitAppRD;
-
- static RoutineDescriptor gDoOpenDocumentRD = BUILD_ROUTINE_DESCRIPTOR(uppAEEventHandlerProcInfo, DoOpenDocument);
- static AEEventHandlerUPP gDoOpenDocument = &gDoOpenDocumentRD;
-
- static RoutineDescriptor gDoPrintDocumentRD = BUILD_ROUTINE_DESCRIPTOR(uppAEEventHandlerProcInfo, DoPrintDocument);
- static AEEventHandlerUPP gDoPrintDocument = &gDoPrintDocumentRD;
- #else
- static AEEventHandlerUPP gDoOpenApp = (AEEventHandlerUPP) DoOpenApp;
- static AEEventHandlerUPP gDoQuitApp = (AEEventHandlerUPP) DoQuitApp;
- static AEEventHandlerUPP gDoOpenDocument = (AEEventHandlerUPP) DoOpenDocument;
- static AEEventHandlerUPP gDoPrintDocument = (AEEventHandlerUPP) DoPrintDocument;
- #endif
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static pascal OSErr SimpleTextCoachHandler(Rect *pRect, Ptr name, long refCon)
- {
- #pragma unused (refCon)
-
- OSErr anErr = noErr;
- WindowRef pWindow = FrontWindow();
- WindowDataPtr pData = GetWindowInfo(pWindow);
-
- if ((pData) && (pData->pGetCoachRectangle))
- anErr = (*(pData->pGetCoachRectangle)) (pWindow, pData, pRect, name);
-
- return(anErr);
-
- } // SimpleTextCoachHandler
-
- // --------------------------------------------------------------------------------------------------------------
- // MAIN INITIALIZE/SHUTDOWN/LOOP ROUTINES
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- static pascal void* StarterThread(void* threadParam)
- {
- #pragma unused(threadParam)
-
- /*
- All threads, including the starter thread, are initially created
- in a suspended state. The starter thread is made ready to run when
- we get an open application or open document event. It runs until
- there are no activate or update events pending, and then starts the
- font menu and Apple Guide threads. This gives much better performance
- for the initial creation and update of a document, because the threads
- (especially the font thread) chew up a lot of time at first.
-
- The starter thread isn't really necessary - we could get the same
- effect by just checking in the event loop for activate/update events -
- but hey, it's a lot easier to do it this way, doesn't cost much, and
- isn't that what threads are for?
- */
-
- for (;;)
- {
- EventRecord er;
-
- YieldToAnyThread();
-
- if (!EventAvail(activMask | updateMask, &er))
- {
- if (gFontThread != kNoThreadID)
- SetThreadState(gFontThread, kReadyThreadState, gFontThread);
- if (gAGThread != kNoThreadID)
- SetThreadState(gAGThread, kReadyThreadState, gAGThread);
-
- break;
- }
- }
-
- gStarterThread = kNoThreadID;
- return NULL;
-
- } // StarterThread
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Initialize
-
- static OSErr CreateThread(ThreadEntryProcPtr pThread, void* threadParam, ThreadID* ptid)
- {
- OSErr anErr;
-
- anErr = NewThread(kCooperativeThread, pThread, threadParam, 0, kNewSuspend,
- &gThreadResults, ptid);
-
- if (anErr == noErr && gStarterThread == kNoThreadID)
- {
- anErr = NewThread(kCooperativeThread, StarterThread, NULL, 0, kNewSuspend,
- &gThreadResults, &gStarterThread);
- if (anErr != noErr)
- DisposeThread(*ptid, &gThreadResults, false);
- // anErr remains != noErr
- }
-
- return anErr;
- }
-
- // --------------------------------------------------------------------------------------------------------------
- // must be in Main because it runs in a thread and we don't want the segment unloaded
- // while some other thread is running
- #pragma segment Main
-
- static OSErr FindSimpleTextGuideFile(FSSpec *pSpec)
- {
- OSErr anErr = fnfErr;
- short numDBs, index;
- short folderIndex;
-
- for (folderIndex = 0; folderIndex < 3; ++folderIndex)
- {
- switch (folderIndex)
- {
- case 0:
- FindFolder(-1, kPreferencesFolderType, false, &pSpec->vRefNum, &pSpec->parID);
- break;
-
- case 1:
- FindFolder(-1, kExtensionFolderType, false, &pSpec->vRefNum, &pSpec->parID);
- break;
-
- case 2:
- FindFolder(-1, kSystemFolderType, false, &pSpec->vRefNum, &pSpec->parID);
- break;
- }
-
- numDBs = AGFileGetDBCount(pSpec->vRefNum, pSpec->parID, kAGFileDBTypeAny, false);
-
- if (!gDontYield)
- YieldToAnyThread();
-
- for (index = 0; index < numDBs; ++index)
- {
- if (!gDontYield)
- YieldToAnyThread();
-
- if (AGFileGetIndDB(pSpec->vRefNum, pSpec->parID, kAGFileDBTypeAny, false, index+1, pSpec) == noErr)
- {
- OSType creator;
-
- if ((AGFileGetHelpMenuAppCreator(pSpec, &creator) == noErr) && (creator == 'ttxt'))
- return(noErr);
- }
- }
- }
-
- return(anErr);
-
- } // FindSimpleTextGuideFile
-
- // --------------------------------------------------------------------------------------------------------------
- // must be in Main because it runs in a thread and we don't want the segment unloaded
- // while some other thread is running
- #pragma segment Main
-
- static pascal void* AGThread(void *threadParam)
- {
- #pragma unused(threadParam)
-
- if ( !(AGGetAvailableDBTypes() & kAGDBTypeBitAny) )
- {
- // if we find one, add it to the help menu and add the right command
- if (FindSimpleTextGuideFile(&gAGSpec) == noErr)
- {
- MenuHandle helpMenu;
-
- if (HMGetHelpMenuHandle(&helpMenu) == noErr)
- {
- Str255 tempString;
- short rnSave;
-
- AGFileGetDBMenuName(&gAGSpec, tempString);
- AppendMenu(helpMenu, tempString);
-
- // since we're in a separate thread, so other resource file may
- // be open in front of SimpleText's resource fork
- rnSave = CurResFile();
- UseResFile(gApplicationResFile);
-
- GetIndString(tempString, kMiscStrings, iHelpMenuCommand);
-
- UseResFile(rnSave);
-
- if (tempString[0] != 0)
- SetItemCmd(helpMenu, CountMItems(helpMenu), tempString[1]);
- }
- }
- }
-
- // if we have a database, then install a coach handler
- if ( (AGGetAvailableDBTypes() & kAGDBTypeBitAny) )
- {
- AGInstallCoachHandler(NewCoachReplyProc(SimpleTextCoachHandler), 0, &gAGCoachRefNum);
- }
-
- gAGThread = kNoThreadID;
- return NULL;
-
- } // AGThread
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Initialize
-
- static void FindAndInstallSimpleTextGuide(void)
- {
- OSErr anErr = fnfErr;
-
- if (gMachineInfo.haveThreads)
- anErr = CreateThread(AGThread, NULL, &gAGThread);
-
- if (anErr != noErr)
- AGThread(NULL);
-
- } // FindAndinstallSimpleTextGuide
-
- // --------------------------------------------------------------------------------------------------------------
- // must be in Main because it runs in a thread and we don't want the segment unloaded
- // while some other thread is running
- #pragma segment Main
-
- static long SortAndAddMenu(MenuHandle menu, Str255 newItem)
- {
- short numInMenu = CountMItems(menu);
- short i;
- Str255 oldItem;
-
- for (i = 1; i <= numInMenu; ++i)
- {
- GetMenuItemText(menu, i, oldItem);
- switch(IUCompString(newItem, oldItem))
- {
- // already in? Return index
- case 0:
- return(i);
- break;
-
- // less than, keep scanning
- case 1:
- break;
-
- // greater than, add back one
- case -1:
- InsertMenuItem(menu, "\pTom Dowdy", i-1);
- SetMenuItemText(menu, i, newItem);
- return(i);
- break;
- }
- }
-
- // fall off the end? add at the end
- InsertMenuItem(menu, "\pTom Dowdy", numInMenu);
- SetMenuItemText(menu, numInMenu+1, newItem);
-
- return(numInMenu+1);
-
- } // SortAndAddMenu
-
- // --------------------------------------------------------------------------------------------------------------
- // must be in Main because it runs in a thread and we don't want the segment unloaded
- // while some other thread is running
- #pragma segment Main
-
- static void AddToGlobalList(gxFont fontID, short fond, Style styleBits)
- {
- if (!gFontMappingList)
- gFontMappingList = (FontMappingHandle)NewHandle(0);
-
- if (gFontMappingList)
- {
- Size oldSize = GetHandleSize((Handle) gFontMappingList);
- FontMappingPtr pList;
-
- SetHandleSize((Handle)gFontMappingList, oldSize + sizeof(FontMappingRecord));
- pList = &(*gFontMappingList)[oldSize/sizeof(FontMappingRecord)];
- pList->fontID = fontID;
- pList->qdFont = fond;
- pList->qdStyle = styleBits;
- }
-
- } // AddToGlobalList
-
- // --------------------------------------------------------------------------------------------------------------
- // must be in Main because it runs in a thread and we don't want the segment unloaded
- // while some other thread is running
- #pragma segment Main
-
- static void AddEachEntry(Handle fond, short* sp, short entries, gxStyle theStyle, MenuHandle menu, short* pStylesUsed)
- {
- gxFont fontID;
- long length;
- short resID;
- OSType resType;
- Str255 resName;
- Style styleBits;
-
- GetResInfo(fond, &resID, &resType, resName);
-
- for (; entries >= 0; --entries)
- {
- if (*sp == 0)
- {
- styleBits = sp[1];
-
- // map the font ID and the style bits for this style into GX space
- (void)GXConvertQDFont(theStyle, resID, styleBits);
-
- if (!gDontYield)
- YieldToAnyThread();
-
- fontID = GXGetStyleFont(theStyle);
- if (fontID)
- length = GXFindFontName(fontID, gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, nil, nil);
- else
- length = 0;
-
- if (!gDontYield)
- YieldToAnyThread();
-
- if (length)
- {
- unsigned char * name;
- short where;
-
- name = (unsigned char*) NewPtr(length+1);
- if (name)
- {
- MenuHandle subMenu;
- short mark;
-
- // add this font to the list we know about
- AddToGlobalList(fontID, resID, styleBits);
-
- // find the family name for this font
- GXFindFontName(fontID, gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, &name[1], nil);
- name[0] = length;
-
- // add the name if new. Then add sub menus
- where = SortAndAddMenu(menu, name);
-
- // do we already have a sub menu? Or does this font have multiple styles?
- GetItemMark(menu, where, &mark);
- if ( (mark != 0) || (GXFindFonts(fontID, 0, 0, 0, 0, 0, nil, 1, gxSelectToEnd, nil) > 1) )
- {
- if (!gDontYield)
- YieldToAnyThread();
-
- // make a new menu or grab the old one
- if (mark == 0)
- subMenu = NewMenu(mFontSubMenusStart + *pStylesUsed, name);
- else
- subMenu = GetMenuHandle(mark);
- DisposePtr((Ptr) name);
-
- length = GXFindFontName(fontID, gxStyleFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, nil, nil);
- if (length)
- {
- name = (unsigned char*) NewPtr(length+1);
- if (name)
- {
- GXFindFontName(fontID, gxStyleFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, &name[1], nil);
- name[0] = length;
- (void) SortAndAddMenu(subMenu, name);
- DisposePtr((Ptr) name);
- }
- }
-
- // if new menu, add to the master
- if (mark == 0)
- {
- InsertMenu(subMenu, -1);
- SetItemCmd(menu, where, hMenuCmd);
- SetItemMark(menu, where, mFontSubMenusStart + *pStylesUsed);
- (*pStylesUsed)++;
- }
- }
- else
- DisposePtr((Ptr) name);
-
- }
- }
-
- } // if (*sp == 0)
-
- sp += 3; /* three elements in the FAT */
-
- if (!gDontYield)
- YieldToAnyThread();
-
- } // for (# entries)
- } // AddEachEntry
-
- // --------------------------------------------------------------------------------------------------------------
- // must be in Main because it runs in a thread and we don't want the segment unloaded
- // while some other thread is running
- #pragma segment Main
-
- static pascal void* FontsThread(void *threadParam)
- {
- MenuHandle menu = (MenuHandle) threadParam;
- long numberFonts;
- long i;
- short stylesUsed = 0;
- gxStyle theStyle;
- Boolean menusAdjusted = false;
-
- theStyle = GXNewStyle();
-
- numberFonts = CountResources('FOND');
- for (i = 1; i <= numberFonts; ++i)
- {
- Handle fond = GetIndResource('FOND', i);
-
- if (!ResError() && fond && *fond)
- do
- {
- short* sp = (short*)(*fond + sizeof(FamRec));
- short entries = *sp++;
-
- AddEachEntry(fond, sp, entries, theStyle, menu, &stylesUsed);
-
- // now that there are some fonts in the font menu, make sure the menu's enabled
- if (!menusAdjusted && CountMItems(menu) > 0)
- {
- AdjustMenus(FrontWindow(), true, false);
- menusAdjusted = true;
- }
-
- } while ((fond = GetNextFOND(fond)) != 0);
-
- } // for (# fonts)
-
- GXDisposeStyle(theStyle);
-
- gFontThread = kNoThreadID;
- return 0;
- } // FontsThread
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Initialize
-
- static OSErr BuildFontMenu(MenuHandle menu)
- {
- OSErr anErr = noErr;
-
- if (gMachineInfo.haveGX)
- {
- (void) DoStartupGX();
-
- // prime the font cache so we don't spend time doing this in the font thread
- GXGetDefaultFont();
-
- anErr = paramErr;
- if (gMachineInfo.haveThreads)
- anErr = CreateThread(FontsThread, menu, &gFontThread);
-
- if (anErr != noErr)
- {
- FontsThread(menu);
- anErr = noErr;
- }
- }
- else
- AppendResMenu(menu, 'FONT');
-
- return(anErr);
-
- } // BuildFontMenu
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Initialize
-
- static OSErr DoInitialize(void)
- {
- short count; // loop counter
- Handle menuBar; // for loading our menus in
- gxGraphicsError anErr = noErr; // any errors we get, none so far
- long version; // version for Gestalt calls
-
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- gAllDone = false;
-
- // check that the system is correct to handle things
- SysEnvirons(1, &gMachineInfo.theEnvirons);
- if (gMachineInfo.theEnvirons.systemVersion < 0x0700)
- {
- // Wait for app to come to front
- for (count = 1; count <= 3; ++count)
- EventAvail(everyEvent, &gEvent);
-
- anErr = eMachineToOld;
- nrequire(anErr, SysEnvirons);
- }
-
- gMachineInfo.lastBalloonIndex = iNoBalloon;
- gMachineInfo.amInBackground = false;
- gMachineInfo.documentCount = 1;
- gMachineInfo.haveQuickTime = (Gestalt(gestaltQuickTime, &version) == noErr);
- gMachineInfo.haveRecording = (Gestalt(gestaltSoundAttr, &version) == noErr) && ((version & (1<<gestaltHasSoundInputDevice)) != 0);
- gMachineInfo.haveTTS = (Gestalt(gestaltSpeechAttr, &version) == noErr) && ((version & (1<<gestaltSpeechMgrPresent)) != 0);
- gMachineInfo.haveGX = (Gestalt(gestaltGXVersion, &version) == noErr);
- gMachineInfo.haveTSM = (Gestalt(gestaltTSMgrVersion, &version) == noErr) && (version >= 1);
- gMachineInfo.haveTSMTE = (Gestalt(gestaltTSMTEAttr, &version) == noErr) && ((version & (1<<gestaltTSMTE)) != 0);
- gMachineInfo.haveDragMgr = (Gestalt(gestaltDragMgrAttr, &version) == noErr) && ((version & (1<<gestaltDragMgrPresent)) != 0) &&
- (Gestalt(gestaltTEAttr, &version) == noErr) && ((version & (1<<gestaltTEHasGetHiliteRgn)) != 0);
- gMachineInfo.haveThreeD = false;
- gMachineInfo.haveAppleGuide = (Gestalt(gestaltHelpMgrAttr, &version) == noErr) && ((version & (1<<gestaltAppleGuidePresent)) != 0);
- gMachineInfo.haveThreads = (Gestalt(gestaltThreadMgrAttr, &version) == noErr) && ((version & (1<<gestaltThreadMgrPresent)) != 0);
-
- #if GENERATINGPOWERPC
- {
- CFragConnectionID connID;
- Ptr mainAddr;
- Str255 errName;
-
- if ( (gMachineInfo.haveQuickTime) && (GetSharedLibrary("\pQuickTimeLib", kPowerPCCFragArch, kFindCFrag, &connID, &mainAddr, errName) != noErr) )
- gMachineInfo.haveQuickTime = false;
- if ( (gMachineInfo.haveTTS) && (GetSharedLibrary("\pSpeechLib", kPowerPCCFragArch, kFindCFrag, &connID, &mainAddr, errName) != noErr) )
- gMachineInfo.haveTTS = false;
- if ( (gMachineInfo.haveGX) && (GetSharedLibrary("\pQuickDrawGXLib", kPowerPCCFragArch, kFindCFrag, &connID, &mainAddr, errName) != noErr) )
- gMachineInfo.haveGX = false;
- if ( (gMachineInfo.haveDragMgr) && (GetSharedLibrary("\pDragLib", kPowerPCCFragArch, kFindCFrag, &connID, &mainAddr, errName) != noErr) )
- gMachineInfo.haveDragMgr = false;
- if ( (gMachineInfo.haveThreads) && (GetSharedLibrary("\pThreadsLib", kPowerPCCFragArch, kFindCFrag, &connID, &mainAddr, errName) != noErr) )
- gMachineInfo.haveThreads = false;
- }
- #endif
-
-
- // initialize text services if they exist
- if (gMachineInfo.haveTSMTE)
- {
- if (InitTSMAwareApplication() != noErr)
- {
- gMachineInfo.haveTSM = false;
- gMachineInfo.haveTSMTE = false;
- }
- }
-
- // save away info we need from the get-go
- gApplicationResFile = CurResFile();
- gCursorRgn = NewRgn();
-
- // load up the menus
- menuBar = (Handle) GetNewMBar(rMenuBar); /* read menus into menu bar */
- anErr = ResError();
- if ( (anErr == noErr) && (menuBar == nil) )
- anErr = resNotFound;
- nrequire(anErr, GetNewMBar);
-
- // install menus
- SetMenuBar(menuBar);
- DisposeHandle(menuBar);
-
- // build the Apple menu
- AppendResMenu(GetMenuHandle(mApple), 'DRVR'); /* add DA names to Apple menu */
-
- // haven't yet done a startup of QuickDraw GX
- if (gMachineInfo.haveGX)
- gMachineInfo.haveStartedGX = false;
-
- // Build the font menu
- anErr = BuildFontMenu(GetMenuHandle(mFont));
- nrequire(anErr, BuildFontMenu);
-
- // insert our heirarchical menus
- {
- MenuHandle menu = GetMenu( mVoices );
- short menuID, itemID;
-
- InsertMenu( menu, hierMenu );
-
- CommandToIDs(cSelectVoice, &menuID, &itemID);
- menu = GetMenuHandle(menuID);
-
- SetItemCmd( menu, itemID, hMenuCmd );
- SetItemMark( menu, itemID, mVoices );
- }
-
- AdjustMenus(nil, true, false);
- DrawMenuBar();
-
- // start up QuickTime, but problems result in us pretending not to have it
- if (gMachineInfo.haveQuickTime)
- if (EnterMovies() != noErr)
- gMachineInfo.haveQuickTime = false;
-
- // Install AppleEvent handlers for the base classes
-
- #define INSTALL(event, handler) \
- AEInstallEventHandler(kCoreEventClass, event, handler, 0, false)
-
- INSTALL (kAEOpenApplication, gDoOpenApp);
- INSTALL (kAEQuitApplication, gDoQuitApp);
- INSTALL (kAEOpenDocuments, gDoOpenDocument);
- INSTALL (kAEPrintDocuments, gDoPrintDocument);
-
- #undef INSTALL
-
- // Install our global dragging procs, but only if we have Drag and Drop. An error results
- // in us pretending that we don't have drag support. Notice that in the test above, we also
- // require TextEdit to have TEGetHiliteRgn avalilable, which is always the case with the
- // present Drag Manager.
-
- if (gMachineInfo.haveDragMgr)
- {
- gGlobalTrackingHandler = NewDragTrackingHandlerProc(GlobalTrackingHandler);
- gGlobalReceiveHandler = NewDragReceiveHandlerProc(GlobalReceiveHandler);
-
- anErr = InstallTrackingHandler(gGlobalTrackingHandler, nil, nil);
-
- if (anErr == noErr)
- {
- anErr = InstallReceiveHandler(gGlobalReceiveHandler, nil, nil);
-
- if (anErr != noErr)
- {
- RemoveTrackingHandler(gGlobalTrackingHandler, nil);
- gMachineInfo.haveDragMgr = false;
- }
- }
- else
- gMachineInfo.haveDragMgr = false;
- }
-
-
- // verify that the AppleGuide database is available, and if it isn't, try to find
- // it from other places -- but don't bother on 2.1, because they made changes
- // to break our location finding (sigh!)
- if (
- (gMachineInfo.haveAppleGuide) &&
- ( (Gestalt('ag_v', &version) != noErr) || (version < 0x00000210) )
- )
- FindAndInstallSimpleTextGuide();
-
-
- return noErr;
-
-
- // EXCEPTION HANDLING
- BuildFontMenu:
- GetNewMBar:
- SysEnvirons:
- ConductErrorDialog(anErr, cNull, cancel);
-
- return anErr;
-
- } // DoInitialize
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Terminate
-
- static OSErr DoTerminate(void)
- {
- OSErr anErr = noErr;
-
- if (gFontThread != kNoThreadID)
- DisposeThread(gFontThread, &gThreadResults, false);
- if (gAGThread != kNoThreadID)
- DisposeThread(gAGThread, &gThreadResults, false);
- if (gStarterThread != kNoThreadID)
- DisposeThread(gStarterThread, &gThreadResults, false);
-
- if (gMachineInfo.haveQuickTime)
- ExitMovies();
-
- if ( (gMachineInfo.haveGX) && (GXGetGraphicsClient() != nil) )
- {
- GXExitPrinting();
- GXExitGraphics();
- }
-
- if (gMachineInfo.haveTSMTE)
- CloseTSMAwareApplication();
-
- if (gMachineInfo.haveDragMgr)
- {
- RemoveReceiveHandler(gGlobalReceiveHandler, nil);
- RemoveTrackingHandler(gGlobalTrackingHandler, nil);
- }
-
- if (gMachineInfo.haveAppleGuide)
- {
- if ((gAGRefNum != -1) && AGIsDatabaseOpen(gAGRefNum))
- {
- AGClose(&gAGRefNum);
- gAGRefNum = -1;
- }
- if (gAGCoachRefNum != -1)
- AGRemoveCoachHandler(&gAGCoachRefNum);
- }
-
- return anErr;
-
- } // DoTerminate
-
- // --------------------------------------------------------------------------------------------------------------
- #pragma segment Main
-
- main(void)
- {
- OSErr anErr;
-
- #ifndef __MWERKS__
- UnloadSeg((Ptr) _DataInit); /* note that _DataInit must not be in Main! */
- #endif
- MaxApplZone(); /* expand the heap so code segments load at the top */
- MoreMasters(); MoreMasters(); MoreMasters(); /* we love handles */
- anErr = DoInitialize();
- UnloadSeg((Ptr) DoInitialize);
- if (anErr == noErr)
- {
- DoEventLoop();
-
- // REVIEW: don't want to unload the segment we're in!!
- // UnloadSeg((Ptr) DoEventLoop);
- DoTerminate();
- }
- return 0;
- } // main
-